反射概述、获取字节码文件方法、Class对象功能、两个重要案例

反射概述

框架:半成品软件。框架的灵魂、可以在框架的基础上进行软件开发,简化编码
反射:将类的各个组成部分封装为其他对象,这就是反射机制

  • 好处:
    1.可以在程序运行过程中,操作这些对象
    2.可以解耦,提高程序的可拓展性

获取字节码文件的三种方法

  1. 调用Class类的forName(全类名)方法 (java的第一阶段)
    多用于配置文件,将类名定义在配置文件中。读取文件,加载类
  2. 已经创建类后可以用 类名.class 来获取字节码文件 (java的第二阶段)
    多用于参数的传递
  3. 已经创建类对象后可以用Object类中的getClass()方法来获取字节码文件 (java的第三阶段)
    多用于获取对象的字节码方式
    代码示例:
public class Person {
   
    public static void main(String[] args) throws Exception {
   
        Student c=new Student();
        Class cls1 = c.getClass();
        Class cls2 = Student.class;
        Class cls3 = Class.forName("test_practice1.Student");
        System.out.println(cls1);
        System.out.println(cls2);
        System.out.println(cls3);

        System.out.println( cls1 == cls2);           //注意==号是比较内存(堆内存)中的地址是否相同
        System.out.println( cls1 == cls3);
    }
}
注:同一个字节码文件(*.class)再一次程序运行过程中,只会被加载一次,
	无论通过哪一种方式获取的class对象都是同一个。

Class对象功能

获取成员变量方法

方法名 作用
Field[] getField() 获取所有public修饰的成员变量
Field getField(String name) 获取name的成员变量值
Field[] getDeclaredFields() 获取所有成员变量 不考虑修饰符(但不能直接设置由private修饰的成员变量)
Field getDeclaredField() 获取成员变量 不考虑修饰符(但不能直接设置由private修饰的成员变量)

代码示例:

public class Person {
   
    public static void main(String[] args) throws Exception {
   
        Student s=new Student();
        Class c1 = Student.class;
        Class c2 = s.getClass();
        Class c3 = Class.forName("test_practice1.Student");
        System.out.println("-----------------");           //Field[] getFields(); 
        Field[] f1 = c1.getFields();
        for(Field x:f1){
   
            System.out.println(x);
        }
        System.out.println("-----------------");           //Field getField(String name); 
        Field cls = c2.getField("cls");
        cls.set(s,"张三");                 //Field类中提供了get()方法和set()方法
        Object o = cls.get(s);
        System.out.println(o);
        System.out.println("-----------------");              //Filed[] getDeclaredFields();
        Field[] f2 = c3.getDeclaredFields();
        for(Field x:f2){
   
            System.out.println(x);
        }
        System.out.println("-----------------");              //Field getDeclaredField(String name);
        Field score = c3.getDeclaredField("id");        
        //注意:不能直接设置成员变量为protected时的成员 即使用setAccessible(true);也不行 依然会报错
        score.setAccessible(true);                                     
//设置private修饰的成员变量时用setAccessible(true);忽略访问权限修饰符的安全检查即可
        score.set(s,99);
        Object o1 = score.get(s);
        System.out.println(o1);
    }
}

获取构造函数方法

方法名 作用
Constructor<?>[] getConstructors() 获取所有构造方法
Constructor<?> getConstructor() 获取构造方法,在获取带参构造函数时只需要加入相应形参即可
Constructor<?>[] getDeclaredConstructors() 获取所有构造方法 无视修饰符
Constructor<?> getDeclaredConstructor() 获取构造方法
public class Person {
   
    public static void main(String[] args) throws Exception {
   
        Class studentClass = Student.class;
        Constructor constructor1 = studentClass.getConstructor();
        System.out.println(constructor1);
        System.out.println("------------");
        Object o = constructor1.newInstance();
        System.out.println(o);
        System.out.println("------------");
        Constructor constructor2 = studentClass.getConstructor(String.class,int.class,String.class,int.class);    //获取带参构造方法需要在形参中添加例如:String.class
        Object o2 = constructor2.newInstance("张三", 1,"001",100);
        System.out.println(o2);
    }
}

获取成员方法

方法名 作用
Method[] getMethods() 获取所有成员方法
Method getmethod(String name,类<?>…parameterTypes) 获取成员方法
Method[] getDeclaredMethods() 获取所有成员方法
Method getDeclaredMethod(String name,类<?>…parameterTypes) 获取成员方法

代码示例:

public class Person {
   
    public static void main(String[] args) throws Exception {
   
        Class studentClass = Student.class;
        Method eat = studentClass.getMethod("eat", String.class);     
        //获取带参构造需要在getMethod()中添加方法名和形参 例:"eat",String.class
        Student s=new Student();
        eat.invoke(s,"苹果");      
        //Object invoke():调用带参方法时invoke()中需要添加上成员变量
		}
}

注:所有带Declared的方法中都可以设置setAccessible(true)来设置和访问private修饰过的构造函数和成员变量,protected修饰的除外

案例

通过反射越过泛型检查用ArrayList集合中添加一个String类型的数据

代码示例:

ArrayList<Integer> array=new ArrayList<Integer>();
array.add(123);
Class<? extends ArrayList> c = array.getClass();          
//先获取ArrayList对象的Class对象,再调用反射机制访问类中的add(Object o);方法添加一个字符串进入该集合
Method add = c.getMethod("add", Object.class);
add.invoke(array,"hello");
System.out.println(array);

**通过反射来调用配置文件中的指定文件和指定的方法

Properties类的运用(Properties常用方法load()、Property(String key))
代码示例:

//加载数据
Properties prop=new Properties();
FileInputStream fis=new FileInputStream("D:\\NewCompiler\\IDEA\\Practice\\src\\test_practice2\\pro.properties");   //配置文件地址
prop.load(fis);  //注意load(InputStream); 传入的是一个输入流
String className = prop.getProperty("className");
String methodName = prop.getProperty("methodName");
Class<?> c1 = Class.forName(className);
Constructor<?> constructor = c1.getConstructor();     //先要调用出构造方法获取一个对象才可以调用对象中的方法
Object o = constructor.newInstance();
Method m = c1.getMethod(methodName);
m.invoke(o);

pro配置文件中的内容:
pro.properties:
className=test_practice2.Teacher
methodName=teach
#键=值
#key=value
全部评论

相关推荐

在笔试的大西瓜很矫健:这跟数分八竿子打不着,先去了解实习要会什么再说找实习吧
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务