黑马程序员--反射

来源:互联网 发布:众途软件多少钱 编辑:程序博客网 时间:2024/06/06 20:57

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------



反射
1:反射机制:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
 对于任意一个对象,都能调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制


2:学习反射需要有以下步骤
A:首先学习字节码文件
B:第二学习 获取字节码文件的构造方法 并创建对象
C:有了对象了,就要学会获取对象中的成员变量
D:能获取对象中的成员变量了,那么还要学习成员方法


1)字节码文件的三种获取方式

①:Object类的getClass()方法:对象.getClass()
Person p = new Person();
Class c = p.getClass();
注意所有同一个类的字节码文件对象(实例)都是同一个(因为一个类就有唯一的字节码文件)
比如:  Person p = new Person();
Class c = p.getClass();


Person p2 = new Person();
Class c2 = p2.getClass();


System.out.println(p == p2);// false
System.out.println(c == c2);// true


②:数据类型的静态的class属性:类名.class
Class c3 = Person.class;


③:通过Class类的静态方法forName(String className)(一般只用最后一种)
Class c4 = Class.forName("cn.itcast_01.Person");


2)反射获取类的构造方法
public Constructor<?>[] getConstructors():所有公共构造方法
public Constructor<?>[] getDeclaredConstructors():所有构造方法 包括私有
public Constructor<T> getConstructor(Class<?>... parameterTypes):获取单个构造方法
比如:
Class c = Class.forName("cn.itcast_01.Person");
Constructor con = c.getConstructor();//获取无参构造,因为没有参数
Object obj = con.newInstance();//用无参构造方法创建对象
System.out.println(obj);


Constructor con = c.getConstructor(String.class, int.class);//获取有参构造,因为有参数
Object obj = con.newInstance("aaa", 20);//用有参构造方法创建对象
System.out.println(obj);
注意:
可变参数:

public static void main(String[] args) {
int a = 10;
int b = 20;
int result = sum(a, b);//随意传任意个参数
System.out.println(result);


int c = 30;
result = sum(a, b, c);//随意传任意个参数
System.out.println(result);


int d = 40;
result = sum(a, b, c, d);//随意传任意个参数
System.out.println(result);


int e = 50;
result = sum(a, b, c, d, e);//随意传任意个参数
System.out.println(result);


}


public static int sum(int... x) {
int result = 0;
for (int i : x) {//底层就会把参数们封装层成一个数组,所以x是个数组
result += i;
}
return result;
}


3)反射获取类的成员变量
Field[] fields = c.getFields();// 获取所有公共的成员变量
Field[] fields = c.getDeclaredFields();// 获取所有的成员变量
Field field = c.getField("age");// 获取单个的成员变量


比如:获取非私有的单个成员变量
// 获取字节码文件对象
Class c = Class.forName("cn.itcast_01.Person");
//获取构造器对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();
// 获取单个的成员变量
Field field = c.getField("age");
field.set(obj, 20);//给obj对象的field字段赋值为20
System.out.println(obj);


    获取私有的单个成员变量
// 获取字节码文件对象
Class c = Class.forName("cn.itcast_01.Person");
// 创建对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();
Field nameField = c.getDeclaredField("name");
nameField.setAccessible(true);//这个地方是暴力访问,是Field父类的方法
nameField.set(obj, "aaa");


4)反射获取类的成员方法
Method[] methods = c.getMethods();// 所有公共方法,包括父类的
Method[] methods = c.getDeclaredMethods();// 本类的所有方法

Method m1 = c.getMethod("show", null);//无参数无返回值
m1.invoke(obj, null);


Method m2 = c.getMethod("function", String.class);//带参数无返回值
m2.invoke(obj, "aaa");


Method m3 = c.getMethod("reutrnValue", String.class,int.class);//带多个参数有返回值 
Object ooo = m3.invoke(obj, "aaa",26);// ooo就是返回的值


Method m4 = c.getDeclaredMethod("hello", null);//私有方法的调用
m4.setAccessible(true);//暴力访问
m4.invoke(obj, null);

例题:
动态创建某个配置文件中提供的一个类的名字的这个类的对象,并执行其方法

Properties prop = new Properties();
FileReader fr = new FileReader("test.properties");
prop.load(fr);
fr.close();

//获取类名
String className = prop.getProperty("className");
//获取方法名
String methodName = prop.getProperty("methodName");

//获取字节码文件对象
Class c = Class.forName(className);

Constructor con = c.getConstructor();
Object obj = con.newInstance();

Method m = c.getMethod(methodName, null);
m.invoke(obj, null);


泛型只是在编译期间(或者是你在写代码期间)强制要求你的做的一些规范,
等编译通过生成了字节码文件后,泛型就会被擦除,运行期间就没有泛型了


ArrayList<Integer> array = new ArrayList<Integer>();


// 获取字节码文件对象
Class c = array.getClass();
Method m = c.getMethod("add", Object.class);
m.invoke(array, "hello");
m.invoke(array, "world");
m.invoke(array, "java");


System.out.println(array);

0 0
原创粉丝点击