java高级之反射

1.理解反射:

【其就是在运行时,它是把类中成员抽取为其他类对象的过程】

2.获取反射Class的三种方式:

【获取之前首先要创建一个类对象,这里就叫做 xw.Class

其一:

通过Class.forName的方式获取:

Class<?> aClass = Class.forName("com.ssm.entity.fanshe.xw");

其二:

通过类名.class 方式获取:

Class<xw> xwClass = xw.class;

其三:

通过对象.getClass();方式获取:

xw xw = new xw();
Class<? extends com.ssm.entity.fanshe.xw> aClass2 = xw.getClass();

3.通过反射类获取对象

【这里我们就直接用第一种方式获取对象】

【注:通过Class类对象,调用newInstance()】

//通过反射字解码获取第一种方式
Class<?> aClass = Class.forName("com.ssm.entity.fanshe.xw");
//通过反射获取类对象,其他两种方式以此类推
xw o = (xw) aClass.newInstance();
System.out.println(o);

4.获取反射类中的属性成员对象

【还是以第一种方式或取对象】

【这里通过 getDeclaredFields() 的方法可以获取本类中所有的属性成员对象(包括公有、私有)】

//通过反射字解码获取第一种方式
Class<?> aClass = Class.forName("com.ssm.entity.fanshe.xw");
//通过反射获取类对象,其他两种方式以此类推
xw o = (xw) aClass.newInstance();
System.out.println(o);

//通过反射过去类属性对象,其返回的是一个数组
//获取本来中所有的类属性对象
Field[] declaredFields = aClass.getDeclaredFields();
for (Field jk:declaredFields) {
    System.out.println("我可以获取到本类中所有的类属性:"+jk);
}

【这里通过 getFields() 的方法可以获取本类以及父类中的公有属性成员对象(注:不包括私有)

//获取本类中所有的公有的类属性对象(包括继承的父类公有类属性)
Field[] fields = aClass.getFields();
for (Field jk2:fields) {
    System.out.println("获取的是所有公共类属性:"+jk2);
}

【这里通过 getDeclaredField("age") 的方法可以获取本类中指定的单个属性成员对象】

//获取本类中指定的单个类属性
Field age = aClass.getDeclaredField("age");
System.out.println("获取的是指定的单个类属性:"+age);

 

5.Field类中具有的常用方法

5.1 setAccessible(true):设置允许访问私有属性

这里咱们首先通过反射的方式为属性成员对象设置参数

在此之前我们所获取的成员对象都是空值

Class<?> aClass = Class.forName("com.ssm.entity.fanshe.xw");
xw o = (xw) aClass.newInstance();
//通过反射来set成员属性值
Field ages = aClass.getDeclaredField("age");
        ages.set(o,66);
        System.out.println("通过反射设置的属性:"+o);

这里打印结果肯定会报错:
Exception in thread "main" java.lang.IllegalAccessException: Class com.ssm.entity.fanshe.demo1 can not access a member of class com.ssm.entity.fanshe.xw with modifiers "private"
	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
	at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
	at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
	at java.lang.reflect.Field.set(Field.java:761)
	at com.ssm.entity.fanshe.demo1.main(demo1.java:33)

 报错的原因是因为咱们设置的成员对象如果是私有的,它不允许访问,【非法访问 】

 这里只需要加上 变量.setAccessible(true); 即可访问私有成员对象即:【授权】

//通过反射设置set属性
Field ages = aClass.getDeclaredField("age");
ages.setAccessible(true);
ages.set(o,66);
System.out.println("通过反射设置的属性:"+o);

打印结果为:

通过反射设置的属性:xw{name = null, age = 66, hobber = null, higeh = null}

5.2 getAnnotation(注解.class):获取属性上的注解对象

这里咱们首先肯定要去自定义一个注解:并且在其中定义一个属性,以便演示 getAnnotation(注解.class)

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE})
public @interface Myzhu {
    public String value();
}

【 如果不清楚怎么自定义注解,可以阅读我上一篇文章写的 java高级之注解

 自定义后,加在类上

随后其直接通过 getAnnotation(注解.class) 就可以获取到注解属性

//通过反射获取注解对象
Myzhu annotation = aClass.getAnnotation(Myzhu.class);
System.out.println(annotation);

 

6.获取方法类对象

6.1 getDeclaredMethods()

通过 getDeclaredMethods() 方法可以获取本类中所有的方法类对象(包括公有、私有、get、set方法)

Class<?> aClass = Class.forName("com.ssm.entity.fanshe.xw");
xw o = (xw) aClass.newInstance();
//通过反射获取本类中所有的方法类对象(包括公有、私有、get、set方法)
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
    System.out.println("获取的是本类中所有的方法"+declaredMethod);
}

 6.2 getDeclaredMethod()

通过 getDeclaredMethod() 方法可以获取本类中指定的方法类对象

 * 值得注意的是,指定获取单个方法类对象需要填写 (String name,Class<?>... param...) 等可变参数

 eg1:

Class<?> aClass = Class.forName("com.ssm.entity.fanshe.xw");
xw o = (xw) aClass.newInstance();
//通过反射获取本类中指定的方法类对象
Method xw01 = aClass.getDeclaredMethod("xw01");
Object invoke = xw01.invoke(o);
System.out.println(invoke);
System.out.println("通过反射获取本类中指定的方法类对象:"+xw01);

 eg2:

//增加可变参数演示
Method xw02 = aClass.getDeclaredMethod("xw02",Integer.class);
xw02.invoke(o,666);


类中方法:
   public String xw02(Integer xw){
        System.out.println("----xw02-----");
        return "返回了公有方法xw02";
    }

如果要指定获取私有方法,那就多添加一个 setAccessible(true);

Class<?> aClass = Class.forName("com.ssm.entity.fanshe.xw");
xw o = (xw) aClass.newInstance();
Method xw03 = aClass.getDeclaredMethod("xw03", Integer.class);
xw03.setAccessible(true);
xw03.invoke(o,555);

【*类中方法中参数定义的什么数据类型,那么使用反射获取类中指定的方法类对象时,可变参数就填什么数据类型】

6.3 getMethods()

//通过反射获取本类及父辈中的所有方法(真的是指所有,本类及父辈的方法)
Method[] methods = aClass.getMethods();
for (Method method : methods) {
    System.out.println("通过反射获取本类及父辈中的所有方法:"+method);
}

 

7.获取构造对象

7.1 getConstructors()

Class<?> aClass = Class.forName("com.ssm.entity.fanshe.xw");
xw o = (xw) aClass.newInstance();
//通过反射获取本类中所有的构造对象
Constructor<?>[] constructors = aClass.getConstructors();
for (Constructor<?> constructor : constructors) {
    System.out.println("通过反射获取本类中所有的构造对象:"+constructor);
}

7.2 getConstructors()

【值得注意的是,这个方法与之前的不同,它只能获取本类中所有的公共构造对象,不再是可以获取本类以及父类的构造对象】

Class<?> aClass = Class.forName("com.ssm.entity.fanshe.xw");
xw o = (xw) aClass.newInstance();
//通过反射获取本类中所有的公共构造对象
Constructor<?>[] constructorss = aClass.getConstructors();
for (Constructor<?> constructor : constructorss) {
    System.out.println("通过反射获取本类中所有的公共构造对象:"+constructor);
}

7.3 Constructor类中常用的方法

7.3.1 getDeclaredConstructor() 指定获取无参构造对象

//只获取无参构造对象
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
System.out.println("只获取无参构造对象:"+declaredConstructor);

7.3.2 getDeclaredConstructor(String name,Class<?>... param...) 指定获取私有有参构造对象

//指定获取有参构造对象
Class<jk> jkClass = jk.class;
Constructor<com.ssm.entity.fanshe.jk> declaredConstructor1 = jkClass.getDeclaredConstructor(String.class);
//获取私有构造对象,这里依然要授权,又称暴力反射
declaredConstructor1.setAccessible(true);
com.ssm.entity.fanshe.jk NineLimit = declaredConstructor1.newInstance("取九极致之术");
System.out.println(NineLimit);

打印结果:
jk{name = 取九极致之术}

class文件:
class jk{
    private String name;

    //公有无参
    public jk() {
    }

    //公有有参
    public jk(String name) {
        this.name = name;
    }

    //私有有参
    private void jk(String name){
        this.name = name;
    }
   }

以上便是java高级反射的内容,如有漏缺,请在下方评论区中留言,我会及时补充

 

posted @ 2023-08-10 20:32  九极致之术  阅读(37)  评论(0编辑  收藏  举报