java反射机制

发布于:2024-10-15 ⋅ 阅读:(87) ⋅ 点赞:(0)

一.类的加载

1.1类的加载概述

当我们的程序在运行后,第一次用到某一个类的时候,会将这个的class文件读取到内存,并将此类所有的信息储存到一个class对象中

1.2 类的加载时机


创建类的实例。
类的静态变量,或者为静态变量赋值。
类的静态方法。
初始化某个类的子类。
直接使用java.exe命令来运行某个主类。
使用反射方式来强制创建某个类或接口对应的
java.lang.Class对象。

1.3 类加载器


类加载器的作用:加载器是Java运行时环境的一部分,负责加
载字节码文件,即将磁盘上的某个class文件读取到内存并生
成Class的对象


类加载器的分类:


        启动类加载器(Bootstrap ClassLoader):负责加载JDK核
心类库,核心类库位置\jdk\jre\lib\下的jar包。注意:
C++编写的加载器,获取启动类加载器后输出结果是null。


        扩展类加载器(Extension ClassLoader):负责加载JDK扩展
类库,类库位置\jdk\lib\ext\下的jar包


       应用程序类加载器(Application ClassLoader):负责加载我
们自定义类的加载器。

当一个类的class文件被类加载器加载到内存后,类的加载器
会创建出此class文件的对象。class文件的对象是Class类的对
象,是反射技术的基石。


获取类加载器的方式:来自Class类型获取类加载器的方法

package com.ll.maven;

public class Demo01 {
        public static void main(String[] args) {
                //获取Demo01类的 类加载器
                ClassLoader classLoader =
                        Demo01.class.getClassLoader();
//sun.misc.Launcher$AppClassLoader@18b4aac2 启
                // 动类加载器
                System.out.println(classLoader);
                //获取启动类加载器 的父类
                ClassLoader parent =
                        classLoader.getParent();
//sun.misc.Launcher$ExtClassLoader@1540e19d 扩
                //展类加载器
                System.out.println(parent);
//获取扩展类加载器 的父类
//输出null C++编写的加载器,获取启动类加载器后
//  输出结果是null。
                System.out.println(parent.getParent());   
        }
     
}

1.4 使用类加载器加载配置文件


在src下面新建一个db.properties文件

加载配置文件

public class Demo02 {
public static void main(String[] args)
throws IOException {
//创建Properties类的对象
Properties prop=new Properties();
//通过类加载器获取一个输入流
InputStream in =
Demo02.class.getClassLoader().getResourceAsStrea
m("db.properties");
//加载配置文件
prop.load(in);
//输出内容
System.out.println(prop);
}
}

二.反射


2.1 反射概述
反射在实际开发中的应用

反射的概念

使用反射操作类成员的前提

2.2 Class对象的获取和常用方法

public class Demo03 {
public static void main(String[] args)throws ClassNotFoundException {
//获取Class对象方式一:Class.forName("全类名")
Class<?> c1 = Class.forName("com.lzw.demo01.Student");
System.out.println(c1);
//获取Class对象方式二:类名.class
Class c2=Student.class;
System.out.println(c2);
//获取Class对象方式三:对象.getClass()
Student stu=new Student();
Class<? extends Student> c3 =
stu.getClass();
System.out.println(c3);
//因为每个类只有一个Class对象,所以不管使用哪种
方式获取到的Class对象都是同一个
System.out.println(c1==c2);//true
System.out.println(c2==c3);//true
}
public class Student {
private String name;//成员变量
private int age;
public Student() {
}
public Student(String name, int age) {//构造方法
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class Demo04 {
public static void main(String[] args)throws Exception{
//获取Student类的字节码对象
Class<Student> c=Student.class;
//String getSimpleName(); 获得类名字符串:
类名
String simpleName = c.getSimpleName();
System.out.println(simpleName);//Student
//String getName(); 获得类全名:包名+类名
String name = c.getName();
System.out.println(name);//com.lzw.demo01.Stude
nt
//T newInstance() ; 创建Class对象关联类的
对象
Student student = c.newInstance();
System.out.println(student);//com.lzw.demo01.St
udent@1540e19d
}
}

2.3 反射之操作构造方法


2.3.1 Constructor类概述


Constructor类:类中的每一个构造方法都是一个Constructor
类的对象
反射之操作构造方法的目的:获得Constructor对象来创建类
的对象

2.3.2 通过反射获取类的构造方法

2.3.3 通过反射执行构造方法

public class Demo01 {
public static void main(String[] args)throws Exception {
//获取Class对象
Class<Student> c = Student.class;
//Constructor[] getConstructors():获得类
中的所有构造方法对象,只能获得public的
Constructor<?>[] c01 =
c.getConstructors();
System.out.println(Arrays.toString(c01));
//Constructor[]
getDeclaredConstructors()
//获得类中的所有构造方法对象,可以是public、
protected、(默认)、private修饰符的构造方法。
Constructor<?>[] c02 =
c.getDeclaredConstructors();
System.out.println(Arrays.toString(c02));
//Constructor getConstructor(Class...
parameterTypes)
//根据参数类型获得对应的Constructor对象,只能
获得public修饰的构造方法
Constructor<Student> c03 =
c.getConstructor();
System.out.println(c03);
Constructor<Student> c04 =
c.getConstructor(String.class, int.class);
System.out.println(c04);
//Constructor
getDeclaredConstructor(Class... parameterTypes)
//根据参数类型获得对应的Constructor对象,可以
是public、protected、(默认)、private修饰符的构造方
法。
Constructor<Student> c05 =
c.getDeclaredConstructor(String.class);
System.out.println(c05);
System.out.println("=======================执行
构造方法==========================");
// 使用c03执行无参构造方法
Student stu01 = c03.newInstance();
System.out.println(stu01);
// 使用c04执行满参构造方法
Student stu02 = c04.newInstance("雄
大",23);
System.out.println(stu02);
//使用c05执行私有构造方法
//设置取消权限检查
c05.setAccessible(true);
Student stu03 = c05.newInstance("熊二");
System.out.println(stu03);
}
}
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
private Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

通过反射操作成员方法;

2.4.1 Method类概述


Method类:每一个成员方法都是一个Method类的对象。
反射之操作成员方法的目的:操作Method对象来调用成员方
法。


2.4.2 通过反射获取类的成员方法

2.4.3 通过反射执行成员方法

public class Demo01 {
public static void main(String[] args)throws Exception {
//获取Class对象
Class<Student> c = Student.class;
//Method[] getMethods()
//获得类中的所有成员方法对象,返回数组,只能获
得public修饰的且包含父类的
Method[] ms01 = c.getMethods();
System.out.println(Arrays.toString(ms01));

//Method[] getDeclaredMethods()
//获得类中的所有成员方法对象,返回数组,只获得本
类的,包括public、protected、(默认)、private的
Method[] ms02 = c.getDeclaredMethods();
System.out.println(Arrays.toString(ms02));

//获取指定的单个方法
Method m01 =
c.getDeclaredMethod("method01");
System.out.println(m01);
Method m02 =
c.getDeclaredMethod("method02", int.class);
System.out.println(m02);
Method m03 =
c.getDeclaredMethod("method03", int.class);
System.out.println(m03);
Method m04 =
c.getDeclaredMethod("method04", int.class);
System.out.println(m04);

//创建Student类的对象
Student stu = c.newInstance();
//调用m01表示的成员方法
m01.invoke(stu);
//调用m02表示的成员方法
m02.invoke(stu,10);
//调用m03表示的成员方法
Object invoke01 = m03.invoke(stu, 20);
System.out.println(invoke01);
//调用m04表示的成员方法
// 设置取消检查(暴力反射)
m04.setAccessible(true);
Object invoke02 = m04.invoke(stu, 30);
2.5 反射之操作成员变量【自学】
2.5.1 Field类概述
Field类:每一个成员变量都是一个Field类的对象。
反射之操作成员变量的目的:通过Field对象给对应的成员变
量赋值和取值
System.out.println(invoke02);
}
}

student类里面的成员方法

public class Student {
public void method01(){
System.out.println("method01...");
}
public void method02(int num){
System.out.println("method02..."+num);
}
public int method03(int num){
System.out.println("method03..."+num);
return num;
}
private int method04(int num){
System.out.println("method04..."+num);
return num;
}
}

2.5 反射之操作成员变量


2.5.1 Field类概述
Field类:每一个成员变量都是一个Field类的对象。
反射之操作成员变量的目的:通过Field对象给对应的成员变
量赋值和取值

2.5.2 通过反射获取类的成员变量

2.5.3 通过反射访问成员变量

        

public class Student {
public String name;
public int age;
private String sex;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
}

public class Demo01 {
public static void main(String[] args)throws Exception{
//获取Class对象
Class<Student> c = Student.class;
//Field[] getFields()
//获得所有的成员变量对应的Field对象,只能获得
public的
Field[] fs01 = c.getFields();
System.out.println(Arrays.toString(fs01));
//Field[] getDeclaredFields();
//获得所有的成员变量对应的Field对象,包括
public、protected、(默认)、private的
Field[] fs02 = c.getDeclaredFields();
System.out.println(Arrays.toString(fs02));
//Field getField(String name)
//根据成员变量名获得对应Field对象,只能获得
public修饰
Field f01 = c.getField("name");
System.out.println(f01);
Field f02 = c.getField("age");
System.out.println(f02);
//Field getDeclaredField(String name)
//根据成员变量名获得对应Field对象,包括
public、protected、(默认)、private的
Field f03 = c.getDeclaredField("sex");
System.out.println(f03);
//创建Student类的对象
Student stu = c.newInstance();
//给f01对象表示的属性赋值和获取值
f01.set(stu,"张三");
Object obj01 = f01.get(stu);
System.out.println(obj01);
//给f02对象表示的属性赋值和获取值
f02.set(stu,23);
Object obj02 = f02.get(stu);
System.out.println(obj02);
//给f03对象表示的属性赋值和获取值
//设置取消权限检查
f03.setAccessible(true);
f03.set(stu,"男");
Object obj03 = f03.get(stu);
System.out.println(obj03);
}
}

三.反射的应用
框架底层:反射+配置文件
在src下创建user.properties


UserService接口

public interface UserService {
public List<User> findAll();
}

UserServiceImpl实现类

public class UserServiceImpl01 implements
UserService{
@Override
public List<User> findAll() {
User stu01=new User("张三",23);
User stu02=new User("李四",24);
List<User> list=new ArrayList<>();
list.add(stu01);
list.add(stu02);
return list;
}
}
public class UserServiceImpl02 implements
UserService{
@Override
public List<User> findAll() {
User stu01=new User("熊大",23);
User stu02=new User("熊二",24);
List<User> list=new ArrayList<>();
list.add(stu01);
list.add(stu02);
return list;
}
}

测试类

public class Demo01 {
public static void main(String[] args)throws Exception{
//存在强耦合 如果使用UserServiceImpl02 需要
修改等号的左边和右边
//UserServiceImpl01
userServiceImpl01=new UserServiceImpl01();
//List<Student> list =
userServiceImpl01.findAll();
//使用多态改进 存在一定的耦合
//如果使用UserServiceImpl02 需要修改等号的右
边
//UserService userService=new
UserServiceImpl01();
//List<Student> list =
userService.findAll();
//使用反射+配置文件
Properties prop=new Properties();
InputStream in =
Demo01.class.getClassLoader().getResourceAsStrea
m("user.properties");
prop.load(in);
String className =
prop.getProperty("className");
//获取Class对象
Class<UserService> c =
(Class<UserService>) Class.forName(className);
//获取构造器对象
Constructor<UserService> constructor =
c.getConstructor();
//创建对象
UserService userService =
constructor.newInstance();
//调用方法
List<User> list = userService.findAll();
System.out.println(list);
}
}


网站公告

今日签到

点亮在社区的每一天
去签到