------- android培训、java培训、期待与您交流! ----------
JAVA之反射
一、反射的概述
JAVA反射机制是在运行状态,对于任意一个类,都能够知道这个类的所有属性和方法。对于任意一个对象,都能掉用他的任意方法和属性。要想获取字节码文件,就要通过Class类的方法来获取。
二、Class类
Class类:
成员变量
Field
成员方法
Constructor
成员方法
Method
获取class文件对象的方式:
1、通过
对象.class获取
2、通过 类名.class获取
3、通过 Class.forName(String name)获取
1、获取Class对象
获取Class对象代码:
package it.heima.reflect;
public class ClassDemo1 {
public static void main(String[] args) throws Exception {
Person p1=new Person();
Person p2=new Person();
//方式一:对象.getClass()
Class p1Class=p1.getClass();
Class p2Class=p2.getClass();
System.out.println(p1==p2);
System.out.println(p1Class==p2Class);
System.out.println("------------------------");
//方式二 类名.class
Class p3Class=Person.class;
Class p4Class=Person.class;
System.out.println(p3Class==p4Class);
System.out.println("------------------------");
//方式三:Class.forName()
Class p5Class=Class.forName("it.heima.reflect.Person");
Class p6Class=Class.forName("it.heima.reflect.Person");;
System.out.println(p5Class==p6Class);
}
}
2、获取构造方法
通过反射获取构造方法并使用:
获取构造函数的方法:
getConstructor(Class<?> ...para)
根据可变参数获取单个公共构造,要传入class文件,如int.class,String.class
getConstructors()
获取所有公共的构造函数,非公共的不能获取
getDeclaredConstructors()
获取所有申明的构造,包括私有的
通过构Class对象创建对象
newInstance()
根据null构造创建一个对象
使用无参的构造函数代码演示:
package it.heima.reflect;
import java.lang.reflect.Constructor;
public class ConstructDemo {
public static void main(String[] args) throws Exception {
Class c=Class.forName("it.heima.reflect.Person");
//Constructor[] constructors=c.getConstructors(); //获取所有Public构造
/*Constructor[] constructors=c.getDeclaredConstructors(); //获取所有申明的构造,包括私有的,不包括父类的
for(Constructor cc:constructors){
System.out.println(cc);
}*/
Constructor cc=c.getConstructor(String.class,int.class,int.class);//只能获取单个Publicd的构造
System.out.println(cc);
Object obj=c.newInstance();
Person p=(Person)obj;
p.show();
System.out.println(obj);
}
}
newInstance()有异常存在,当无参构造是private时,存在一个异常,
IllegalAccessException
- 如果该类或其 null 构造方法是不可访问的。
使用带参的构造函数代码演示:
package it.heima.reflect;
import java.lang.reflect.Constructor;
public class ConstructorDemo2 {
public static void main(String[] args) throws Exception {
Class c=Class.forName("it.heima.reflect.Person");
Constructor con=c.getConstructor(String.class,int.class,int.class);
Object obj=con.newInstance("张三",20,200000);
System.out.println(obj);
}
}
注:Class和Constuctor类都有newInstance(),Class类的只能创建非私有的无参构造,Constuctor的newInstance可以创建带参的对象。
使用私有的构造函数代码演示:
package it.heima.reflect;
import java.lang.reflect.Constructor;
public class ConstructorDemo3 {
public static void main(String[] args) throws Exception{
Class c=Class.forName("it.heima.reflect.Person");
Constructor cc=c.getDeclaredConstructor(String.class);
cc.setAccessible(true);//暴力反射
Object obj=cc.newInstance("张三");
System.out.println(obj);
}
}
获取到私有的构造函数后,不能创建对象,否则有异常出现
需要设置该构造的权限。(暴力反射
)
setAccessible(boolean)---------->true
然后才能创建对象。
3、获取成员变量
获取成员变量类的方法:
getField(String name)
getDeclaredField(String name)
getFields()
成员变量的方法:
set(Object obj,value)
get(Object obj)
setAccessible(boolean)
成员变量的使用代码演示:
package it.heima.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class GetFieldDemo {
public static void main(String[] args) throws Exception{
Class c=Class.forName("it.heima.reflect.Person");
/*//Field[] field=c.getFields(); 获取所有公共的成员
//Field[] field=c.getDeclaredFields(); 获取所有申明的成员
for(Field f:field){
System.out.println(f);
}*/
Constructor cc=c.getDeclaredConstructor();
Object o=cc.newInstance();
Field field=c.getDeclaredField("age");
field.setAccessible(true);
field.set(o, 20);
Field field2=c.getDeclaredField("name");
field2.set(o, "张三");
Field field3=c.getDeclaredField("salary");
field3.set(o, 2000);
System.out.println(o);
}
}
注:成员变量一般是私有的,要注意Field.setAccessible(true);
3、获取并使用成员方法
获取成员变量类的方法:
getMethod(String name,class<?>...)
getDeclared
Method
(String name,class<?>..)
getDeclared
Methods()
获取所有自己的方法
get
Methods()
获取所有的公共方法,包括父亲的
成员变量的获取和使用代码演示:
package it.heima.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class MethodDemo {
public static void main(String[] args) throws Exception{
Class c=Class.forName("it.heima.reflect.Person");
/* //Method[] method=c.getMethods(); //获取所有公共的方法,包括父类的
Method[] method=c.getDeclaredMethods(); //获取所有自身的方法
for(Method item:method){
System.out.println(item);
}*/
Constructor constructor=c.getDeclaredConstructor();
Object obj=constructor.newInstance();
Method method=c.getDeclaredMethod("show");
method.invoke(obj);//调用obj的method方法
Method method2=c.getDeclaredMethod("method",String.class);
method2.setAccessible(true);
method2.invoke(obj, "你好");
Method method3=c.getDeclaredMethod("stringMethod",String.class);
method3.setAccessible(true);
Object s=method3.invoke(obj, "我的");
System.out.println(s);
}
}
三、配置文件的应用
1、通过配置文件调用方法
package it.heima.reflect;
import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;
public class PropertiesDemo {
//通过配置文件调用方法
public static void main(String[] args) throws Exception {
Properties properties=new Properties();
FileReader fileReader=new FileReader("E:\\JavaSE_WorkSpace\\AllTest\\src\\it\\heima\\reflect\\Properties.txt");
properties.load(fileReader);
fileReader.close();
String className=properties.getProperty("className");
String methodName=properties.getProperty("methodName");
Class c=Class.forName(className);
Constructor con=c.getDeclaredConstructor();
con.setAccessible(true);
Object obj=con.newInstance();
Method method=c.getDeclaredMethod(methodName);
method.setAccessible(true);
method.invoke(obj);
}
}
package it.heima.reflect;
import java.lang.reflect.Method;
import java.util.ArrayList;
//通过泛型绕开
public class GenericityDemo {
public static void main(String[] args) throws Exception {
ArrayList<Integer> arrayList=new ArrayList<>();
Class c=ArrayList.class;
Method method=c.getMethod("add", Object.class); //泛型默认是Object类型的,这是一个泛型方法。如果传入其他类型会出现异常,NoSuchMethod
method.invoke(arrayList, "hello");
System.out.println(arrayList);
}
}
注意:getMethod()时要注意参数的类型,否则有NoSuchMethodException