Java中Class类的使用,反射机制

反射:把Java中的各种数据(方法、属性、构造器、类名)映射成一个个Java对象。

可以通过Class类创建一个类,获取类的信息,操作类的属性。

 


准备一个Uer类,在 package lurenjia.leaning; 包下,有int  id、int  age、String  name三个私有属性,及其对应的set/get方法(其中  setId  为  private  私有方法),一个无参构造器和一个有参构造器。

package lurenjia.leaning;

public class User {
    private int id;
    private int age;
    private String name;

    public int getId() {
        return id;
    }

    private void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public User() {
    }

    public User(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
}
查看User 类

一、获取Class对象

方式一:有此类的对象,直接通过getClass()方法获取。

public static void main(String[] args) {
        User t= new User();
        Class cl =t.getClass();
}

方式二:能够直接使用类的时候,通过类名.class获取。

public static void main(String[] args) {
       Class cls = User.class;
}

方式三:通过静态方法Class.forName("包名.类名")。

public static void main(String[] args) throws ClassNotFoundException {
        Class cls = Class.forName("lurenjia.leaning.User");
}

方式四:通过子类的类对象获取

//获取子类的类对象
Class son  = Son.class;
//获取自身的类对象
Class father = son.getSuperclass();

二、通过Class对象获取类信息

1、获取类的实例(Instance)

public static void main(String[] args) throws Exception{
        Class cls = Class.forName("java.lang.String");
        //jdk9以前,使用Class对象创建一个String对象
        String str0 = (String)cls.newInstance();
        //jdk9推荐方式:使用构造器创建对象,所以它推荐所有类加入无参构造器。
        String str1 = (String) cls.getConstructor().newInstance("iloveyou");
}

2、获取类名(Name)

    getName      包括包名

    getSimpleName   不包括包名

public static void main(String[] args) throws Exception{
        Class clszz = Class.forName("lurenjia.leaning.User");
        //获取类名,包括包名
        System.out.println(clszz.getName());
        //获取类名,不包括包名
        System.out.println(clszz.getSimpleName());
    }

运行结果:

3、 获取属性(Filed)、方法(Method)、构造器(Constructor):

public static void main(String[] args) throws Exception{
        Class clszz = Class.forName("lurenjia.leaning.User");
        //获取指定public属性,不存在会抛出异常
        //Field field=clszz.getField("id");
        //获取指定属性
        Field field2=clszz.getDeclaredField("id");
        //获取所有的public属性,包括它的父类的public属性
        Field[] fields=clszz.getFields();
        //获取所有的属性
        Field[] fields2=clszz.getDeclaredFields();
        
        //获取指定public方法
        Method method = clszz.getMethod("setId", int.class);
        //获取指定方法,带参数则输入参数类型.class,无参则null
        Method method2 = clszz.getDeclaredMethod("setId", int.class);
        //获取所有的public方法
        Method[] methods = clszz.getMethods();
        //获取所有的方法
        Method[] methods2 = clszz.getDeclaredMethods();
        
        //获取public无参构造器
        Constructor constructor = clszz.getConstructor();
        //获取指定public带参数的构造器
        Constructor constructor2 = clszz.getConstructor(int.class,int.class,String.class);
        //获取所有public构造器
        Constructor[] constructors = clszz.getConstructors();
        //获取所有的构造器
        Constructor[] constructors2 = clszz.getDeclaredConstructors();
    }

总结:

Class对象获取信息:

    获取public:使用:get  属性(Filed)、方法(Method)、构造器(Constructor)。

    获取非public:使用:getDeclared   属性(Filed)、方法(Method)、构造器(Constructor)。

    获取全部:+s,返回数组。获取public会获取到父类的,Declared则会获取自身的。


三、通过Class对象操作实际对象

1、使用对象的方法:

public static void main(String[] args) throws Exception{
        //创建一个User对象
        User u1 = new User(1,18,"二狗子");
        //获取User类的Class对象
        Class c = u1.getClass();
        //获取User类的setId方法
        Method method = c.getDeclaredMethod("setName", String.class);
        //操作u1中的setName方法
        method.invoke(u1,"老苗子");
    }

2、操作对象的属性:

public static void main(String[] args) throws Exception{
        //创建一个User对象
        User u1 = new User(1,18,"二狗子");
        //获取User类的Class对象
        Class c = u1.getClass();
        //获取User类的name属性
        Field field = c.getDeclaredField("name");
        //将此反射对象的accessible标志设置为指示的布尔值,值为true表示反射对象应该在使用Java语言访问控制时抑制检查。
        field.setAccessible(true);
        //操作u1的属性
        field.set(u1,"老苗子");
        //获取u1的属性
        System.out.println(field.get(u1));
    }

注意:如果属性为私有属性,我们可以通过设置accessible标识来抑制检查,达到访问效果:

setAccessible(true);   (设置是否禁用 访问的安全检查。)它可以提供反射运行的速度。 

posted @ 2022-11-19 18:30  在博客做笔记的路人甲  阅读(173)  评论(0编辑  收藏  举报