java—反射
java反射的概念
反射被认为是动态语言的关键,反射机制允许程序在运行期间获取任何类的内部信息。并能操作其内部方法属性。
- 反射机制的核心是在程序允许时动态加载类并获取类的详细信息,从而操作类或者对象的属性和方法。本质是JVM得到class对象后再通过对象进行反编译,从而获取对象的各种信息。
- java属于先编译后运行的语言,程序中对象的类型在编译期就确定下来了,而当程序运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM,通过反射,可以在运行时动态的创建对象并调用其属性。不需要在编译期知道运行的对象是谁。
看完后还是感觉很抽象。
*获得Class:主要有三种方法*
(1)Object–>getClass
(2)任何数据类型(包括基本的数据类型)都有一个“静态”的class属性
(3)通过class类的静态方法:forName(String className)(最常用)
三种方式中,常用第三种,第一种对象都有了还要反射干什么,第二种需要导入类包,依赖太强,不导包就抛编译错误。一般都使用第三种,一个字符串可以传入也可以写在配置文件中等多种方法。
通过反射获取构造器并创建对象创建对象
*(1)使用Class对象的newInstance()方法来创建Class对象对应类的实例。*
这种方法必须要有可以访问的构造方法才能创建对象,如果c的构造方法是private的,那么调用newInstance方法会抛出IllegalAccessException异常。
Class<?> c = String.class;
Object str = c.newInstance();
(****2)先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建对象,这种方法可以用指定的构造器构造类的实例。****
通过这种方法就算构造方法是private的也能创建对象,只需要
//获取class对象
Class<?> aClass = Class.forName("cn.luoxin88.javabase.mianshi.Myclass");
//获取构造器(包括private)
Constructor constructor = aClass.getDeclaredConstructor();
//设置private方法为可访问,不设置的话也会抛出IllegalAccessException
constructor.setAccessible(true);
//通过构造器创建对象
Myclass a = (Myclass) constructor.newInstance();
通过反射获取方法并调用
通过反射获取属性并修改其值
public class Demo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
Class<?> aClass = Class.forName("cn.luoxin88.javabase.mianshi.Myclass");
//私有构造器必须通过getDeclaredConstructor获取且调用前需要设置为可访问
Constructor constructor1 = aClass.getDeclaredConstructor();
constructor1.setAccessible(true);
Myclass a = (Myclass) constructor1.newInstance();
//其他构造方法直接通过getConstructor就可以获取了,括号里面是参数对应类的class
//需要注意的是如果方法的参数是int,则必须是int.class而不能是Interger.class
Constructor constructor2 = aClass.getConstructor(int.class);
Myclass b = (Myclass) constructor2.newInstance(3);
//方法的获取与调用,获取和构造器差不多,从class对象获取,调用的时候需要指定调用该方法的对象
// 私有方法同样需要设置为可访问后才能调用
//参数是要获取的方法名,如果方法有参数的话还要再后面加上参数类的class对象
Method method1 = aClass.getDeclaredMethod("f");
method1.setAccessible(true);
//通过invoke方法调用,第一个参数是调用该方法的对象,后面跟参数
method1.invoke(a);
//有参数的公共方法
Method method2 = aClass.getMethod("f",int.class);
method2.invoke(a,5);
//属性的获取与修改
//私有属性
Field field1 = aClass.getDeclaredField("name");
field1.setAccessible(true);
//获取属性值要制定对象,私有属性要先设置为可访问
System.out.println("修改前的name:"+field1.get(a));
field1.set(a,15);
System.out.println("修改后的name:"+field1.get(a));
//共有属性
Field field2 = aClass.getField("age");
System.out.println("修改前的age:"+field2.get(a));
field2.set(a,123);
System.out.println("修改后的age:"+field2.get(a));
}
}
class Myclass {
private Myclass() {
}
public Myclass(int a) {
}
private int name = 1;
public int age = 2;
private void f() {
System.out.println("private");
}
public void f(int a) {
System.out.println("public" + a);
}
}
总而言之,通过反射可以获取到类的构造器,方法和属性,并对其进行调用或者修改