java反射

反射定义

官方解释:反射通常用来检测和改变java在虚拟机中的表现。
通俗来讲反射就是通过非常规手段在程序运行时修改程序的行为。

反射入口

Class
反射其实就是为一个类提供通用说明书Class, 注意的是 Class 是首字母大写,不同于 class 小写,class 是定义类的关键字,而 Class 的本质也是一个类,因为在 Java 中一切都是对象。
把 Java 虚拟机类似于高速公路,那么 Class 就是用来描述公路上飞驰的汽车,也就是我前面提到的规格说明书。

Class的获取
反射的入口是 Class,但是反射中 Class 是没有公开的构造方法的,所以就没有办法像创建一个类一样通过 new 关键字来获取一个 Class 对象。获取方式如下:
1.通过Object.getClass()。
对于一个对象而言,如果这个对象可以访问,那么调用 getClass() 方法就可以获取到了它的相应的 Class 对象。
public class Reflect {
    public static void get(){
        System.out.println("hello");
    }

    public static void main(String[] args) {
        Reflect reflect=new Reflect();
        Class clazz=reflect.getClass();
    }
}
值得注意的是,这种方法不适合基本类型如 int、float 等等。

2.通过.class获取

public class Reflect {
    public static void get(){
        System.out.println("hello");
    }

    public static void main(String[] args) {
       
        Class clazz2=Reflect.class;
        Class a=int.class;
        Class b=String.class;
    }
}
3.通过Class.forname()
public class Reflect {
    public static void get(){
        System.out.println("hello");
    }
    @SneakyThrows
    public static void main(String[] args) {

       Class c=Class.forName("com.ssm.study.Reflect");
    }
}

Class的名字

涉及到Api
  Class.getName();
Class是一个入口,代表引用,基本数据类型,对象数组。
1.当Class代表一个引用时,getName()返回的是二进制字符串。eg:"com.ssm.study.Reflect"
2.当Class代表一个基本类型时,getName()返回的是它们的关键字。eg:int.class->int
3.当Class代表一个基本类型的数组时,getName()返回 [[[I 这样的字符串
public class Reflect {
    public static void get(){
        System.out.println("hello");
    }
    @SneakyThrows
    public static void main(String[] args) {

       Class c=Class.forName("com.ssm.study.Reflect");
        c.getName();
       c.getCanonicalName();
       c.getSimpleName();
       Class a=int.class;
       Class b=new int[]{}.getClass();
        System.out.println(a.getName());
        System.out.println(b.getName());
        System.out.println(c.getName());
    }
}
效果:


Class获取修饰符

Class的修饰符主要有:
  • 用来限制作用域,如 public、protected、priviate。
  • 用来提示子类复写,abstract。
  • 用来标记为静态类 static。
  • 注解。
  System.out.println(Modifier.toString(Reflect.class.getModifiers()));
效果:

获取Class的成员

class的成员包括Field、Method、Constructor。
getDeclaredField() 获取的是 Class 中被 private 修饰的属性。 
getField() 方法获取的是非私有属性,并且 getField() 在当前 Class 获取不到时会向祖先类获取。
//获取所有的属性,但不包括从父类继承下来的属性
public Field[] getDeclaredFields() throws SecurityException {}

//获取自身的所有的 public 属性,包括从父类继承下来的。
public Field[] getFields() throws SecurityException {}
eg:
public class Father {
    private int a;
     int b;
     public int d;
}
public class Son extends Father {
    private int c;
    public int e;
}
public class Reflect {


    @SneakyThrows
    public static void main(String[] args) {

        System.out.println(Modifier.toString(Reflect.class.getModifiers()));
        Class son=Son.class;
        System.out.println(son.getDeclaredField("b"));
    }
}


 
 
public class Father {
    private int a;
     int b;
     public int d;
}
public class Son extends Father {
 
 
    private int c;
    public int e;
}
public class Reflect {


    @SneakyThrows
    public static void main(String[] args) {

        System.out.println(Modifier.toString(Reflect.class.getModifiers()));
        Class son=Son.class;
        System.out.println(son.getDeclaredField("b"));
    }
}

public class Reflect {


    @SneakyThrows
    public static void main(String[] args) {

        System.out.println(Modifier.toString(Reflect.class.getModifiers()));
        Class son=Son.class;
       /* System.out.println(son.getDeclaredField("b"));*/
        Field[] fields=son.getDeclaredFields();
        for (Field filed:
                fields ) {
            System.out.println("getDeclaredFields():"+filed.getName());
        }

        Field[] fields1=son.getFields();
        for (Field filed:
                fields1 ) {
            System.out.println("getFields():"+filed.getName());
        }
    }
}


tips:如何获取父类中的非public的属性
public class Reflect {

    public  void say()

    {
        System.out.println("hello");
    }

    @SneakyThrows
    public static void main(String[] args) {
        Field[] declaredFields = Son.class.getSuperclass().getDeclaredFields();
        for (Field field:declaredFields
             ) {
            System.out.println("Son父类的属性"+field.getName());
        }
    }
}
效果:

两张图对比说明:



获取Constructor
代码1:
public class Father {
    private int a;
     int b;
     public int d;

    public Father() {
        super();
    }
}
public class Son extends Father {
    private int c;
    public int e;

    private Son() {
        super();

    }

    public Son(int c, int e) {
        super();
        this.c = c;
        this.e = e;
    }
}
public class Reflect {


    @SneakyThrows
    public static void main(String[] args) {

        System.out.println(Modifier.toString(Reflect.class.getModifiers()));
        Class son=Son.class;
       /* System.out.println(son.getDeclaredField("b"));*/
        Field[] fields1=son.getDeclaredFields();
        for (Field filed:
                fields1 ) {
            System.out.println("getDeclaredFields()"+filed.getName());
        }

        Field[] fields2=son.getFields();
        for (Field filed:
                fields2 ) {
            System.out.println("getFields()"+filed.getName());
        }
        Constructor[] constructors1=son.getDeclaredConstructors();
        for (Constructor constructor:
        constructors1) {
            System.out.println("getDeclaredConstructors:"+constructor.toString());
        }

        Constructor[] constructors2=son.getConstructors();
        for (Constructor constructor:
                constructors2) {
            System.out.println("getConstructors:"+constructor.toString());
        }
    }
}
效果:

通过invoke调用方法

public class Reflect {

    public  void say(String...args)

    {

        for (String s:args
             ) {
            System.out.println(s);
        }
    }

    @SneakyThrows
    public static void main(String[] args) {
        //获取字节码对象
       Class clazz=Class.forName("com.ssm.study.Reflect");
       //获取一个对象
        Constructor constructor = clazz.getConstructor();
        Reflect r= (Reflect) constructor.newInstance();
        String[] s=new String[]{"aa","bb"};
        //获取method对象
        Method getA = clazz.getMethod("say", String[].class);
        //调用invoke方法来调用
        //将传递进去的s强转为Object类型
         getA.invoke(r, new Object[]{s});
         //s重新包装成一个Object数组
         getA.invoke(r,(Object) s);

    }
}
 

效果:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值