海码充电站的技术专栏 java Coder

javaSE- - 反射

2018-12-18
watermelon


反射

前言

在研究源码时,javaSE中的反射应用及jdk中对反射的实现还是挺重要的。

1:常用反射api

1:获取类对象
	第一种使用 Class.forName 静态方法
	Class clz = Class.forName("java.lang.String");
	
	第二种使用 .class 方法
	Class clz = String.class;
	
	第三种使用类对象的 getClass() 方法
	String str = new String("Hello");
	Class clz = str.getClass();
创建类对象
    第一种通过 Class 对象的 newInstance() 方法
	Class clz = Apple.class;
	Apple apple = (Apple)clz.newInstance();
	
	第二种通过 Constructor 对象的 newInstance() 方法
	Class clz = Apple.class;
	Constructor constructor = clz.getConstructor();
	Apple apple = (Apple)constructor.newInstance();
	
	通过 Constructor 对象创建类对象可以选择特定构造方法而通过 Class 对象则只能使用默认的无参数构造方法下面的代码就调用了一个有参数的构造方法进行了类对象的初始化
  
	Class clz = Apple.class;
	Constructor constructor = clz.getConstructor(String.class, int.class);
	Apple apple = (Apple)constructor.newInstance("红富士", 15);
2:获取属性
    我们通过 Class 对象的 getFields() 方法可以获取 Class 类的属性但无法获取私有属性
	Class clz = Apple.class;
	Field[] fields = clz.getFields();
	for (Field field : fields) {
		System.out.println(field.getName());
	}
	
	输出结果是
	price
	
	而如果使用 Class 对象的 getDeclaredFields() 方法则可以获取包括私有属性在内的所有属性

	Class clz = Apple.class;
	Field[] fields = clz.getDeclaredFields();
	for (Field field : fields) {
		System.out.println(field.getName());
	}
	
	输出结果是
	name
	price
	  
	与获取类属性一样当我们去获取类方法类构造器时如果要获取私有方法或私有构造器则必须使用有 declared 关键字的方法
3:获取方法
    cla.getDeclaredMethods();
    cla.getDeclaredMethod(String var1, Class... var2);
4:获取构造器
    cla.getDeclaredConstructors();
    cla.getDeclaredConstructor(Class... var1)
5:获取父类
    obj.getClass().getSuperclass()
6:获取接口
obj.getClass().getInterfaces();
7:获取全部子类或全部接口的实现类

方案:取到全部的包路径,然后一个一个去判断 获取全部子类或接口的全部实现

2:应用示例

//获得类完整的名字
String className = c2.getName();
System.out.println(className);//输出com.ys.reflex.Person
        
//获得类的public类型的属性。
Field[] fields = c2.getFields();
for(Field field : fields){
   System.out.println(field.getName());//age
}
        
//获得类的所有属性。包括私有的
Field [] allFields = c2.getDeclaredFields();
for(Field field : allFields){
    System.out.println(field.getName());//name    age
}
        
//获得类的public类型的方法。这里包括 Object 类的一些方法
Method [] methods = c2.getMethods();
for(Method method : methods){
    System.out.println(method.getName());//work waid equls toString hashCode等
}
        
//获得类的所有方法。
Method [] allMethods = c2.getDeclaredMethods();
for(Method method : allMethods){
    System.out.println(method.getName());//work say
}
   
//获得指定的属性
Field f1 = c2.getField("age");
System.out.println(f1);
//获得指定的私有属性
Field f2 = c2.getDeclaredField("name");
//启用和禁用访问安全检查的开关,值为 true,则表示反射的对象在使用时应该取消 java 语言的访问检查;反之不取消
f2.setAccessible(true);
System.out.println(f2);
                
//创建这个类的一个对象
Object p2 =  c2.newInstance();
//将 p2 对象的  f2 属性赋值为 Bob,f2 属性即为 私有属性 name
f2.set(p2,"Bob");
//使用反射机制可以打破封装性,导致了java对象的属性不安全。 
System.out.println(f2.get(p2)); //Bob
        
//获取构造方法
Constructor [] constructors = c2.getConstructors();
for(Constructor constructor : constructors){
    System.out.println(constructor.toString());//public com.ys.reflex.Person()
}

3:jdk中对反射的实现

参考下引用:大白话…

引用:


Comments

Content