JavaSE进阶之Java反射常用方法整理

文章目录

    • 1、Java反射机制概述
    • 2、获取Class的三种方式
      • 2.1、第一种
      • 2.2、第二种
      • 2.3、第三种
    • 3、通过反射实例化对象
    • 4、通过反射机制访问对象属性
    • 5、通过反射机制调用方法(重点)
    • 6、通过反射机制调用指定构造器

1、Java反射机制概述

反射机制有什么用?

通过java语言中的反射机制可以操作字节码文件。优点类似于黑客。(可以读和修改字节码文件)通过反射机制可以操作代码片段。(class文件)

反射机制的相关类在哪个包下?

java.lang.reflect.*

反射机制相关的重要的类有哪些?

java.lang.Class:代表整个字节码,代表一个类型,代表整个类。
java.lang.reflect.Method:代表字节码中的方法字节码。代表类中的方法。
java.lang.reflect.Constructor:代表字节码中的构造方法字节码。代表类中的构造方法。
java.lang.reflect.Field:代表字节码中的属性字节码。代表类中的成员变量(静态变量+实例变量)


2、获取Class的三种方式

2.1、第一种

Class c = Class.forName(“完整类名带包名”);

try {
  	Class c1 = Class.forName("java.lang.String");   //c1代表String类型
    Class c2 = Class.forName("java.util.Date");  //c2代表Date类型
    Class c3 = Class.forName("java.lang.Integer");  //c3代表Integer类型
    Class c4 = Class.forName("java.lang.System");  //c4代表System类型
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

Class.forName()

  1. 静态方法
  2. 方法的参数是一个字符串
  3. 字符串需要的是一个完整类名
  4. 完整类名必须带有包名。java.lang包也不能省略

2.2、第二种

Class c = 对象.getClass();

在这里插入图片描述

public static void main(String[] args) {
        Class c1 = null;
        Class c2 = null;
        Class c3 = null;
        try {
            c1 = Class.forName("java.lang.String");
            c2 = Class.forName("java.util.Date");
            c3 = Class.forName("java.lang.Integer");
            Class c4 = Class.forName("java.lang.System");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        String str = "abcd";  //字符串对象
        Class aClass = str.getClass();    //aClass代表String.class的字节码文件,aClass代表Stirng类型·
        System.out.println(aClass == c1);  //true(==判断的是对象的内存地址)

        Date date = new Date();
        Class cdate = date.getClass();
        System.out.println(cdate == c2);  //true(cdate和c2两个变量中保存的内存地址都是一样的,都指向方法区中的字节码文件)
}

在这里插入图片描述


2.3、第三种

Class c = 任何类型.class;

public static void main(String[] args) {
        Class c1 = null;
        Class c2 = null;
        Class c3 = null;
        try {
            c1 = Class.forName("java.lang.String");
            c2 = Class.forName("java.util.Date");
            c3 = Class.forName("java.lang.Integer");
            Class c4 = Class.forName("java.lang.System");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        
        //Java语言中任何一种类型,包括基本数据类型,它都有.class属性
        Class stringClass = String.class;  //stringClass代表Stirng类型
        Class dateClass = Date.class; //dateClass代表Date类型

        System.out.println(stringClass == c1);
        System.out.println(dateClass == c2);
    }

在这里插入图片描述


3、通过反射实例化对象

public class Main {

    public static void main(String[] args) {
        try {
        	//通过反射机制,获取Class,通过Class来实例化对象
            Class aClass = Class.forName("com.dong.Person");
            Object o = aClass.newInstance();
            System.out.println(o);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }

    }

}

//Person类
class Person {

}

在这里插入图片描述

成功创建对象

newInstance()这个方法会调用Person这个类的无参构造方法,完成对象的创建。

class Person {
    public Person() {
        System.out.println("运行无参构造方法");
    }
}

在这里插入图片描述

如果定义了有参构造方法但没有无参构造方法就会报错

class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }
}

JavaSE进阶之Java反射常用方法整理_第1张图片

所以,一般最好带上无参构造方法


4、通过反射机制访问对象属性

Student类

public class Student {
    private String name;
    protected int age;
    boolean sex;
    public int no;
    public static final double MATH_PI = 3.1415926;
}
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class student = Class.forName("com.dong.Student");

        Object o = student.newInstance();  //o就是Student对象(底层调用无参数构造方法)

        //获取no属性(根据属性的名称来获取Field)
        Field no = student.getDeclaredField("no");

        no.set(o,123);  //给obj对象的no属性赋值123

        System.out.println(no.get(o));
}

在这里插入图片描述

获取私有属性

public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class student = Class.forName("com.dong.Student");

        Object o = student.newInstance();  //o就是Student对象(底层调用无参数构造方法)

        //获取私有的name
        Field name = student.getDeclaredField("name");

        //给name属性赋值
        name.set(o,"皮皮虾");

        System.out.println(name.get(o));
}

JavaSE进阶之Java反射常用方法整理_第2张图片

访问报错

解决办法:打破封装
在这里插入图片描述

public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class student = Class.forName("com.dong.Student");

        Object o = student.newInstance();  //o就是Student对象(底层调用无参数构造方法)

        //获取私有的name
        Field name = student.getDeclaredField("name");

        //打破封装
        name.setAccessible(true);

        //给name属性赋值
        name.set(o,"皮皮虾");

        System.out.println(name.get(o));
}

在这里插入图片描述

setAccessible(true)这样设置后,在外部也可以访问private

反射机制缺点:打破封装可能会给不法分子留下机会!!!


5、通过反射机制调用方法(重点)

User类

public class User {

    int no;
    int age;

    /**
     * 登陆方法
     */
    public boolean login(String name,String password) {
        if ("admin".equals(name) && "123".equals(password)) {
            return true;
        }
        return false;
    }

    /**
     * 退出
     */
    public void logout() {
        System.out.println("系统已经安全退出");
    }
}

测试

public class Main {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class aClass = Class.forName("com.dong.User");

        //创建对象
        Object obj = aClass.newInstance();

        //获取Method
        Method login = aClass.getDeclaredMethod("login", String.class, String.class);
        Object admin = login.invoke(obj, "admin", "123");
        System.out.println(admin);

        Method logout = aClass.getDeclaredMethod("logout");
        logout.invoke(obj);

    }

}

在这里插入图片描述

getDeclaredMethod():参数1:指明获取的方法的名称,参数2:指明获取的方法的形参列表

invoke():参数1:方法的调用者,参数2:给方法形参赋值的实参

反射机制,让代码很具有通用性,可变化的内容都是写到配置文件中,将来修改配置文件之后,创建的对象不一样了,调用的方法也不同了,但是java代码不需要任何改动。这就是发射机制能力。


6、通过反射机制调用指定构造器

JavaSE进阶之Java反射常用方法整理_第3张图片

public class Main {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class aClass = Class.forName("com.dong.User");


        Constructor declaredConstructor = aClass.getDeclaredConstructor(int.class, int.class);

        Object o = declaredConstructor.newInstance(1, 2);
        System.out.println(o);
    }

}

在这里插入图片描述

getDeclaredConstructor():参数:指明构造器的参数列表


  创作不易,如果帮到大家的话,可以点赞关注和收藏哦,谢谢各位!

博主更多博文

在这里插入图片描述

你可能感兴趣的:(Java,java,反射,类,class)