Java - 反射

 定义

存放于 java.lang.reflect 包中。new属于静态编译,反射属于动态编译,只有在运行时才会去获得该对象的实例。对于任意一个类都能知道并调用它所有的属性和方法。

优缺点

优点:降低类之间的耦合性,只需要给我一个路径就可以拿到我需要的东西,具体操作与你无关。

缺点:由于可以获取类中私有成员,破坏了类的封装使类变得不安全,还会降低程序性能。

第一步:获取类对象 Class

方法说明补充
类名.class基本数据类型的封装类可以通过 .TYPE 的方式获取其Class对象,但要注意TYPE实际上获取的是封装类对应的基本类型的Class对象的引用。因此 int.class==Integer.TYPE 返回true,int.class==Integer.class 返回 false。需要导包,依赖性太强
Object.getClass ()通过实例获取对应类对象。都有对象了还反射个什么
Class.forName (类的完整路径)传入的路径是"包名.类名",需要处理可能抛出的 ClassNotFoundException 异常。常用这种,传入的是字符串,可以做成配置文件
//类名获取
Class<Person> personClass = Person.class;
//对象获取
Person jinx = new Person("Jinx", 18);
Class<? extends Person> jinxClass = jinx.getClass();
//路径获取
Class<?> aClass = Class.forName("com.example.kotlinnotes.Person.java");

第二步:获取构造函数 Constructor

获取构造说明
getDeclaredConstructors ()获取全部的构造方法
getConstructors ()只能获取全部的public构造方法
getDeclaredConstructor (Class<?>... parameterTypes) 

获取指定构造方法(传入的是 形参的类名.class)

getConstructor (Class<?>... parameterTypes) 只能获取指定的public构造方法(传入的是 形参的类名.class)
//获取全部构造函数
Constructor<?>[] declaredConstructors = pathClass.getDeclaredConstructors();
//只获取全部的public构造函数
Constructor<?>[] constructors = pathClass.getConstructors();
//获取指定构造函数
Constructor<?> declaredConstructor = pathClass.getDeclaredConstructor(String.class, int.class);
declaredConstructor.setAccessible(true);    //如果是public构造就不用这步
Son sonPrivate = (Son) declaredConstructor.newInstance("sonPrivate", 18);  //通过有参构造创建实例
//只获取指定的public构造函数
Constructor<?> constructor = pathClass.getConstructor();
Son sonPublic = (Son) constructor.newInstance();    //通过无参构造创建实例

第三步:创建实例对象 newInstance

创建对象说明
Class 实例的 newInstance ()只能通过无参构造创建对象
Constructors 实例的 newInstance ()可以通过有参构造创建对象
//只能通过无参构造创建实例
Class<?> pathClass = Class.forName("com.example.kotlinnotes.knowledge.Son");
Son sonFromClass = (Son) pathClass.newInstance();

第四步:获取调用字段及方法 Field & Method

获取字段 (Class的方法)说明
getDeclaredFeilds ()获取全部字段(不包括超类的)
getFeilds ()只能获取全部全部的public字段(包括超类的)
getDeclaredFeild (String fieldName)获取指定字段
getFeild (String fieldName)只能获取指定的public字段
使用字段(Feild的方法)说明

get (Object obj)

getByte (Object obj)

getShort (Object obj)

getInt (Object obj)

getLong (Object obj)

getDouble (Object obj)

getFloat (Object obj)

getChar (Object obj)

getBoolean (Object obj)

获取成员变量的值

(如果是基本类型的话有对应方法,避免类型转换的开销)

set (Object obj)

setByte (Object obj)

setShort (Object obj)

setInt (Object obj)

setLong (Object obj)

setDouble (Object obj)

setFloat (Object obj)

setChar (Object obj)

setBoolean (Object obj)

设置成员变量的值

(如果是基本数据类型的话有对应方法,避免类型转换的开销)

getType ()

getGenericType ()

获取字段声明的数据类型,返回的是Class对象

如果字段声明的数据类型带泛型(参数化类型)则会带上泛型的数据类型,返回的是Type对象,否则打印出来的和上面一样

方法(ParameterizedType的方法)说明
getRawType ()获取数据类型
getActualTypeArguments()获取泛型的数据类型
Class<?> pathClass = Class.forName("com.example.kotlinnotes.knowledge.Son");
Son sonFromClass = (Son) pathClass.newInstance();

//获取全部字段
Field[] declaredFields = pathClass.getDeclaredFields();
//只获取全部的public字段
Field[] fields = pathClass.getFields();
//获取指定字段
Field sonAgePrivate = pathClass.getDeclaredField("sonAgePrivate");
sonAgePrivate.setAccessible(true);    //如果是pubnlic字段就不用这个
sonAgePrivate.getInt(sonFromClass); //0
sonAgePrivate.setInt(sonFromClass,100);
sonAgePrivate.getInt(sonFromClass);  //100
//只获取指定的public字段
Field sonIsMalePublic = pathClass.getField("sonIsMalePublic");
sonIsMalePublic.getBoolean(sonFromClass); //false
sonIsMalePublic.setBoolean(sonFromClass,true);
sonIsMalePublic.getBoolean(sonFromClass);  //true
Class<?> pathClass = Class.forName("com.example.kotlinnotes.knowledge.Son");
//基本类型的字段
Field sonIsMalePublic = pathClass.getField("sonIsMalePublic");
Class<?> typeBasic = sonIsMalePublic.getType();
System.out.println(typeBasic);  //boolean
Type genericType1 = sonIsMalePublic.getGenericType();
System.out.println(genericType1);  //boolean
System.out.println(genericType1.getTypeName());  //boolean
//自定义类型的字段
Field father = pathClass.getField("father");
Class<?> typeCustomize = father.getType();
System.out.println(typeCustomize);    //class com.example.kotlinnotes.knowledge.Father
Type genericType2 = father.getGenericType();
System.out.println(genericType2);  //class com.example.kotlinnotes.knowledge.Father
System.out.println(genericType2.getTypeName());  //com.example.kotlinnotes.knowledge.Father
//【List】参数化类型(带泛型的数据类型)
Field list = pathClass.getField("list");
Class<?> listType = list.getType();
System.out.println(listType);    //class java.util.ArrayList
Type genericType3 = list.getGenericType();
System.out.println(genericType3);   //java.util.ArrayList<java.lang.Integer>
System.out.println(genericType3.getTypeName()); //java.util.ArrayList<java.lang.Integer>
//【Map】参数化类型(带泛型的数据类型)
Field map = pathClass.getField("map");
Class<?> mapType = map.getType();
System.out.println(mapType);  //interface java.util.Map
Type genericType4 = map.getGenericType();
System.out.println(genericType4);    //java.util.Map<java.lang.String, java.lang.Integer>
if(genericType4 instanceof ParameterizedType){
    //强制类型转换
    ParameterizedType type = (ParameterizedType) genericType4;
    //获取数据类型
    Type rawType = type.getRawType();
    System.out.println(rawType);  //interface java.util.Map
    //获取泛型的数据类型
    Type[] actualTypeArguments = type.getActualTypeArguments();
    Arrays.stream(actualTypeArguments).forEach(System.out::println);    //class java.lang.String    class java.lang.Integer
}else{
    System.out.println("获取出错!");
}
获取方法(Class的方法)说明
getDeclaredMethods ()获取全部方法(不包括继承的,仅本类/接口中的)
getMethods ()只能获取全部的public方法(包括继承来的:本类/接口中的+父类/接口中的+Object中的)
getDeclaredMethod (String methodName, Class<?>... parameterTypes)获取指定方法(传入的是 方法名+形参的类名.class)
getMethod (String methodName, Class<?>... parameterTypes)只能获取指定的public方法(传入的是 方法名+形参的类名.class)
使用方法(Method的方法)说明
invoke (Object obj, Object... args) 调用方法(参数一是调用该方法的实例对象,后面传方法的参数)
setAccessible (boolean flag) 如果调用的方法非public,则需要将Method对象设置为true
Class<?> pathClass = Class.forName("com.example.kotlinnotes.knowledge.Son");
Son sonFromClass = (Son) pathClass.newInstance();

//获取全部方法
Method[] declaredMethods = pathClass.getDeclaredMethods();
//只能获取全部的public方法(包括继承)
Method[] methods = pathClass.getMethods();
//获取指定方法
Method sonMethodPrivate = pathClass.getDeclaredMethod("sonMethodPrivate", String.class, int.class);
sonMethodPrivate.setAccessible(true);   //如果是public方法就不用这个
sonMethodPrivate.invoke(son,"调用指定的方法",2);
//只能获取指定的public方法
Method sonMethodPublic = pathClass.getMethod("sonMethodPublic", String.class, int.class);
sonMethodPublic.invoke(son,"调用指定的public方法",1);

其他方法

方法(Class的方法)说明
isPrimitive ()
isArray ()
isAnnotation ()
isInterface ()
isEnum ()
isAnonymousClass ()

基础类型?
集合类?
注解类?

接口?

枚举类?

匿名内部类?

getName ()

getSimpleName ()

getPackage ()

getModifiers ()

getDeclaredClasses ()

getDeclaringClass ()

获取完整类名(含包名路径)

获取类名

获取包信息

获取类的访问权限

获取内部类

获取外部类

附:Son.class代码、Father.class 代码

public class Father {
    private int fatherAgePrivate;
    private String fatherNamePrivate;
    public boolean fatherIsMalePublic;

    public Father() {
        this.fatherNamePrivate = "Default";
        this.fatherAgePrivate = 0;
        this.fatherIsMalePublic = false;
    }

    private Father(String fatherNamePrivate, int fatherAgePrivate) {
        this.fatherNamePrivate = fatherNamePrivate;
        this.fatherAgePrivate = fatherAgePrivate;
        this.fatherIsMalePublic = false;
    }

    public Father(String fatherNamePrivate, int fatherAgePrivate, boolean fatherIsMalePublic) {
        this.fatherNamePrivate = fatherNamePrivate;
        this.fatherAgePrivate = fatherAgePrivate;
        this.fatherIsMalePublic = fatherIsMalePublic;
    }

    public void fatherMethodPublic(String str, int num){
        System.out.println("fatherMethodPublic:" + str + num);
    }

    private void fatherMethodPrivate(String str, int num){
        System.out.println("fatherMethodPrivate:" + str + num);
    }
}
public class Son extends Father {
    private String sonNamePrivate;
    private int sonAgePrivate;
    public boolean sonIsMalePublic;
    public Father father;
    public ArrayList<Integer> list;
    public Map<String,Integer> map;

    public Son() {
        this.sonNamePrivate = "Default";
        this.sonAgePrivate = 0;
        this.sonIsMalePublic = false;
    }

    private Son(String sonNamePrivate, int sonAgePrivate) {
        this.sonNamePrivate = sonNamePrivate;
        this.sonAgePrivate = sonAgePrivate;
        this.sonIsMalePublic = false;
    }

    public Son(String sonNamePrivate, int sonAgePrivate, boolean sonIsMalePublic) {
        this.sonNamePrivate = sonNamePrivate;
        this.sonAgePrivate = sonAgePrivate;
        this.sonIsMalePublic = sonIsMalePublic;
    }

    public void sonMethodPublic(String str, int num) {
        System.out.println("sonMethodPublic:" + str + num);
    }

    private void sonMethodPrivate(String str, int num) {
        System.out.println("sonMethodPrivate:" + str + num);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值