关于Java反射

1.认识反射

反射定义:指的是对象的反向处理。根据对象倒推类的组成。

  • 反射核心处理在于Object类的方法】:取得类的class对象。

    public final native Class<?> getClass();

    Class类描述各个类的组成(成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。)。

1.1 Class对象的三种实例化方式

任何一个类的Class对象由JVM加载类后产生(该对象在JVM中全局唯一,有且只有一个),用户只能调用指定方法来取得该对象。

  1. 任何类的对象可以通过调用Object类提供的getClass()取得该类Class对象。
  2. “类名称.class”可以直接根据某个具体类来取得其Class对象。
  3. 调用Class类的静态方法Class.forName(String className)传入类的全名称来取得其Class对象。
    对照下面例子看一下:
//根据类正向产生对象
Date date = new Date();
//1.通过类对象.getClass()
System.out.println(date.getClass());
//2.通过类名称.Class
System.out.println(Date.class);
//3.通过调用Class类提供的静态方法forName(String className)
System.out.println(Class.forName("java.util.Date"));

:class java.util.Date
  class java.util.Date
  class java.util.Date

取得一个类的Class对象后:可以通过反射来实例化对象。

注意:在运行期间,一个类,只有一个Class对象产生。

三种方式常用第三种,第一种对象都有了还要反射干什么。第二种需要导入类的包,依赖太强,不导包就抛编译错误。一般都第三种,一个字符串可以传入也可写在配置文件中等多种方法。
  • 在Class 类中有如下方法:只能调用类中无参构造且无参构造必须是public权限。
        Date date = new Date();
        1.取得类的Class对象
        Class<Date> cls = (Class<Date>) Class.forName("java.util.Date");
        2.通过反射取得Date类实例化对象
        Date date = cls.newInstance();
        System.out.println(date);

2.反射与类操作

2.1 反射取得父类、父接口信息

class Person{}
interface INews{}
interface IMessage{}
class Student extends Person implements INews,IMessage{}

public class Test3{
    public static void main(String[] args) {
        //--------------- 首先取得Class对象 ------------------
        Class<Student> cls = Student.class;
        
        //-------------- 2.1.1 取得类的包名称 ----------------
        System.out.println("取得类的包名称:"+cls.getPackage().getName());
        
        //-------------- 2.1.2 取得父类的Class对象 ------------
        System.out.println("取得父类的Class对象:"+cls.getSuperclass().getName());
        
        //-------------- 2.1.3 取得实现的父接口 -----------------
        Class<?>[] classes = cls.getInterfaces();
        for(Class cla : classes){
            System.out.println("取得实现的父接口:"+cla.getName());
        }
    }
}

运行结果:

取得类的包名称:www.bit
取得父类的Class对象:www.bit.Person
取得实现的父接口:www.bit.INews
取得实现的父接口:www.bit.IMessage

2.1.1 取得类的包名称

  • public Package getPackage()

2.1.2 取得父类的Class对象

  • public native Class<? super T> getSuperclass();

2.1.3 取得实现的父接口

  • public Class<?>[ ] getInterfaces();

特殊情况:基本类型都有自己的Class对象。

public class Test3{
    public static void main(String[] args) {
        Class<?> cls = int.class;  //基本类型,八大基本类型都有自己的class对象
        Class<?>cls1 = Integer.class;
        System.out.println(cls);
        System.out.println(cls1);
    }
}
运行结果:
int
class java.lang.Integer

2.2 反射调用构造方法—Constructor(描述类中构造方法)

class Student {

    //------------------构造方法------------------
    //--- 默认的构造方法
    Student(String str) {
        System.out.println("(默认)的构造方法 s=" + str);
    }

    //--- 公有无参的构造方法
    public Student() {
        System.out.println("公有无参方法。");
    }

    //--- 公有有参的构造方法
    public Student(char name) {
        System.out.println("姓名: " + name);
    }

    //--- 有多个参数的构造方法
    public Student(String name, int age) {
        System.out.println("姓名:" + name + "年龄:" + age);
    }

    //--- 受保护的构造方法
    protected Student(boolean n) {
        System.out.println("受保护的有参构造  n = " + n);
    }

    //--- 私有有参构造方法
    private Student(int age) {
        System.out.println("私有的构造方法  年龄:" + age);
    }

}
public class Test3{
    public static void main(String[] args)throws Exception {
        //首先要加载Class对象
        Class<Student> cls = Student.class;

        System.out.println("------------获取公有、无参的构造方法----------");
        {
            Constructor con = cls.getConstructor(null);
            //1>、因为是无参的构造方法所以类型是一个null,不写也可以:这里需要的是一个参数的类型,切记是类型
            //2>、返回的是描述这个无参构造函数的类对象。
            System.out.println("con = " + con);
        }
        System.out.println("---------------获取公有的有参构造---------");
        {
            Constructor con = cls.getConstructor(char.class);
            System.out.println(con);
        }
        System.out.println("--------------获取私有的有参构造------------");
        {
            Constructor con = cls.getDeclaredConstructor(int.class);
            System.out.println(con);
        }
        System.out.println("-------------取得类中所有public构造方法-------");
        {
            Constructor<?>[] con = cls.getConstructors();
            for(Constructor constructor : con){
                System.out.println(constructor);
            }
        }
        System.out.println("------------取得类中全部构造方法-----------");
        {
            Constructor<?>[] con = cls.getDeclaredConstructors();
            for(Constructor constructor :con){
                System.out.println(constructor);
            }
        }
        System.out.println("-------------class类提供了实例化对象的方法---------");
        {
            Student per = (Student) cls.newInstance(); //第一种方式
            //Object obj = cls.newInstance();  //第二种方式
        }
        System.out.println("************Constructor获取私有构造方法,并调用***************");
        {
            Constructor con = cls.getDeclaredConstructor(int.class);
            System.out.println(con);
            //调用构造方法
            con.setAccessible(true);//暴力访问(忽略掉访问修饰符)
            Object obj = con.newInstance(20);
        }
    }
}

运行结果:

------------获取公有、无参的构造方法----------
con = public www.bit.Student()
---------------获取公有的有参构造 a1 ---------
public www.bit.Student(char)
--------------获取所有类型(这里是私有)的有参构造  a2 ------------
private www.bit.Student(int)
-------------取得类中所有public构造方法 b1 ------
public www.bit.Student(java.lang.String,int)
public www.bit.Student(char)
public www.bit.Student()
------------取得类中全部构造方法 b2 -----------
private www.bit.Student(int)
protected www.bit.Student(boolean)
public www.bit.Student(java.lang.String,int)
public www.bit.Student(char)
public www.bit.Student()
www.bit.Student(java.lang.String)
-------------class类提供了实例化对象的方法---------
公有无参方法。
************Constructor获取私有构造方法,并调用***************
private www.bit.Student(int)
私有的构造方法  年龄:20

a) 取得类中指定参数类型的构造

  • public Constructor getConstructor(Class<?> … parameterTypes):
  • public Constructor getDeclaredConstructor(Class<?> … parameterTypes)

b) 取得类中所有构造方法

  • public Constructor<?>[ ] getConstructors() throws SecurityException:
    只能取得类中public权限的构造方法
  • public Constructor<?>[ ] getDeclaredConstructors() throws SecurityException
    可以取得类中全部构造方法,包含私有构造

c) Constructor类提供了实例化对象的方法:

  • public T newInstance(Object … initargs):可以调用类中其他有参构造

2.3 反射调用普通方法(核心)—Method(描述类中普通方法)

a) 取得类中指定名称的普通方法

  • public Method getMethod(String name,Class<?> … parameterTypes)
    需要传入<名称,参数类型>因为方法有重载
    在本类以及父类中找指定参数的的Public权限

  • public Method getDeclaredMethod(String name,Class<?> … parameterTypes)
    在本类中找指定参数和名称的任何权限的方法

b) 取得类中全部普通方法

  • public Method[] getMethods() throws SecurityException
    取得本类以及父类中所有public方法

  • public Method[] getDeclaredMethods() throws SecurityException
    取得本类中全部普通方法,包含私有方法

拿到方法之后就要进行调用,否则光拿到就没有任何意义。所以请看下面的方法

c) Method 类中提供调用类中普通方法的API

  • public Object invoke(Object obj,Object … args)

2.4 反射调用类中普通属性—Field(描述类中普通属性)

a) 取得类中指定属性

  • public Field getField(String name)throws NoSuchFieldException,SecurityException

  • public Field getDeclaredFields()throws NoSuchFieldException,SecurityException

b) 取得类中全部属性

  • public Field[] getFileds() throws SecurityException
    取得本类以及父类中所有public属性
  • public Field[] getDeclaredFields() throws SecurityException
    取得本类中全部普通属性,包含私有属性

c) Field类提供设置与取得属性方法

设置属性:

  • public void set(Object obj,Object value)
    取得属性:
  • public Object get(Object obj)
    取得属性类型:
  • public Class<?> getType()

2.5 动态设置封装

Constructor、Method、Field类都是AccessibleObject的子类。
AccessibleObject提供动态设置封装方法: (在本次JVM进程中有效,且只能通过反射,可以多次调用)

  • public void setAccessible(boolean flag) throws SecurityException
    true就可以访问。

猜你喜欢

转载自blog.csdn.net/qq_41420688/article/details/84590194
今日推荐