咱们一起来探讨 Java 的反射吧

一.为什么使用反射?反射是什么?

反射可以解决在编译时无法预知对象和类是属于那个类的,要根据程序运行时的信息才能知道该对象和类的信息的问题。在两个人协作开发时,你只要知道对方的类名就可以进行初步的开发了。

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

二.从案例学习如何使用反射

public class Man implements AnimalBaseSkill{

    public int sex=-1;    
    private String name;    
    private Man(int sex, String name) {      
        this.sex = sex;        
        this.name = name;    
    }    
    public Man() {         
    }    
    public int getSex() {        
        return sex;    
    }    
    public void setSex(int sex) {        
        this.sex = sex;    
    }    
    public String getName() {        
        return name;    
    }    
    public void setName(String name) {        
        this.name = name;    
    }

    @Override
    public void eat() {}


    private class Clan {    
        String clanName="default family";    
        public Clan(String familyName) {        
            this.clanName = familyName;    
        }    
        public Clan() {    

        }    
        public String getClanName() {        
            return clanName;    
        }    
        public void setClanName(String clanName) {        
            this.clanName = clanName;    
        }
    }
}
1.如何通过反射获取Person对象?
  1. Class.forName(String clazzName)静态方法
  2. 调用类的class属性,Person.class返回的就是Person的class对象(推荐使用)
  3. 调用某个对象的getClass()方法

eg.

Class class1 = Class.forName("com.ch.java.reflect.Man");
Class class2 = Man.class;
Class class3 =Man.getClass();

但是只有方法一可以获取私有内部类:

Class class_clan=Class.forName("com.ch.java.reflect.Man$Clan");

获取Class后,然后通过Class获取构造器,通过newInstance()就可以获取该对象:

Constructor constructor=class1.getConstructor(null); 
Man man= (Man) constructor.newInstance();

但是内部类的对象要像下面获取,原因会在(如何获取类构造器?)讲解

Constructor constructor=class_clan.getConstructor(Man.class, String.class);
Object family=constructor.newInstance(man, "123");
2.如何获取类构造器?
  1. getConstructor(Class…parameterTypes):返回此Class对象对应类的带指定形参的public构造器,返回参数:Connstructor
  2. getConstructors():返回此Class对象对应类的所有public构造器,返回参数:Constructor[]
  3. getDeclaredConstructor(Class…parameterTypes):返回此class对象对应类的带指定参数的构造器,与构造器的访问权限无关,返回参数:Constructor[]
  4. getDeclaredConstructors():返回此class对象对应类的所有构造器,与构造器的访问权限无关,返回参数:Constructor[]

person对象的构造器获取很简单,但是person内部类的family对象的构造器如何获取?它的坑点在哪里呢?

for (Constructor constructor1 : class_clan.getDeclaredConstructors()) {
    System.out.println(constructor1.toString()); } 打印:
public com.ch.java.reflect.Man$Clan(com.ch.java.reflect.Man,java.lang.String)
public com.ch.java.reflect.Man$Clan(com.ch.java.reflect.Man)
3.获取类成员方法
  1. getMethod(String name,Class<?>…parameterTypes):返回此class对象对应类的带指定形参的public方法,返回参数:Method
  2. Method[] getMethods():返回此class对象所表示的类的所有public方法
  3. Method getDeclaredMethod(string name,Class<?>…parameterTypes):返回此class对象对应类的带指定形参的方法,与方法访问权限无关
  4. Method[] getDeclaredMethods():返回此class对象对应类的全部方法,与方法的访问权限无关
class_1.getMethods();
class_1.getDeclaredMethods();
for (Method method : methods) { 
     System.out.print(method.getName()+" "+method.getReturnType()+" "); 
     int i=0;  
     for (Class<?> aClass : method.getParameterTypes()) {
         i++; 
         System.out.print("params"+i+" "+aClass.toString()+" "); 
      }  
      System.out.print"\n");
}
打印:
getName class java.lang.String
setName void params1 class java.lang.String
color void params1 int
getSex int
setSex void params1 int
Disconnected from the target VM, address: '127.0.0.1:52500', transport: 'socket'wait void 
wait void params1 long params2 int
wait void params1 long
equals boolean params1 class java.lang.Object *********toString class java.lang.String 
hashCode int
getClass class java.lang.Class
notify void 
notifyAll void
4.获取类成员变量
  1. Field getField(String name):返回此class对象对应类的指定名称的public成员变量
  2. getFields():返回此class对象对应类的所有public成员变量,返回参数:Field[]
  3. getDeclaredField(String name):返回此class对象对应类的指定名称的成员变量,与成员变量访问权限无关。返回参数:Field
  4. getDeclaredFields():返回此class对象对应类的全部成员变量,与成员变量的访问权限无关,返回参数:Field[]
Field[] fields=class_1.getFields();
Field[] fields=class_1.getDeclaredFields();
for (Field field : fields) { 
    System.out.println(field.getName()+" "+field.getType());
}
打印:
sex int
age int
5.其他

获取该类内部类

Class<?>[] getDeclaredClasses():返回该class队形对应类里包含的全部内部类

获取该类对象所在的外部类

Class<?> getDeclaringClass():返回该Class对象对应类所在的外部类

获取该类对象对应类所实现的接口

Class<?>[] getInterfaces():返回该Class对象对应类所实现的全部接口

获取该类对象对应类所继承的父类

Class<? super T> getSuperclass():返回该Class对象对应类的超类的Class对象

获取该类对象对应类的修饰符、所在包、类名等基本信息

int getModifiers():返回此类或接口的所有修饰符,修饰符由publicprotectedprivatefinalstaticabstract等对应的常量组成,返回的整数应使用Modifier工具类的方法来解码,才可以获取真是的修饰符

Package getPackage():获取该类的包

String getName():以字符串形式返回此CLass对象所表示的类的简称

判断该类是否为接口、枚举、注解类型

boolean isAnnotation():返回此class对象是否表示一个注解类型

boolean isAnnotationPresent(Class<? extends Annotation>annotationClass):判断此Class对象是否使用类Annotation修饰

boolean isAnonymousClass():返回此class对象是否是一个匿名类

boolean isArray():返回此class对象是否表示一个数组类

boolean isEnum():返回此class对象是否表示一个枚举

boolean isInterface():返回此class对象是否表示一个接口

boolean isInstance(Object obj):判断obj是否是此class对象的实例,该方法可以完全代替instanceof操作符
    原文作者:Android
    原文地址: https://juejin.im/entry/58d550fc2f301e007e76cca2
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞