Java-反射以及反射调用类中方法

认识反射

反射是对象的反射处理操作。

先来看看“正”操作。

在默认情况下,必须要先导入一个包,而后才能产生类的实例化对象。
如下就是一个正操作。

import java.util.Date;//导入的包

public class Test{
    public static void main(String[] args){
        Date date = new Date();//产生Date类的实例化对象
        //...使用产生的date引用调用类中的方法,属性
    }
}

而反操作就是根据对象来取得对象的源,反射的核心处理就在于Object类中的一个方法:

取得类的Class对象
public final native Class<?> getClass();
//返回类型为泛型表示可以是任意的Class对象,Class描述的就是一个类。

例如:

import java.util.Date;//导入的包

public class Test{
    public static void main(String[] args){
        Date date = new Date();//产生Date类的实例化对象

        //反射通过对象获取到对象的来源
        System.out.println(date.getClass());
    }
}

输出:

class java.util.Date

通过date.getClass() (对象.getClass())可以得到Class类的对象。

反射的第一步就是拿到Class对象,而拿到Class类对象有三种实例化模式

首先,我想先说一下什么是Class类,为什么我们可以通过对象反射得到Class对象,得到Class对象我们能干什么。

什么是Class类
Class类是反射的源头,也是对整个类的描述,具有相应类的一切信息。

在Java中一切皆对象,而对象都是由类产生的,也就是Java中有各种各样的类,而这些类都是同一种类—>Class类。
举个例子来说:
人,有各种各样的人 而这些人属于一类,那就是人类
同理,java类,有各种各样的类, 而这些类属于同一类,那就是Class类。

区分: class是关键字,定义类时使用,Class是类名

一个类被类加载器加载到内存中占用一片存储空间,这个空间中的内容称为类的字节码,不同的类的字节码是不同的,所以他们在内存中的内容是不同的,而各个字节码可以用不同的Class类对象来表示。

比如:Date date = new Date();
当使用到Date类时,类加载器会将Date类加载到内存中,以字节码的形式存在。而Date.getClass();就是得到属于Date的那份字节码,返回Date类。每个类中包含的属性是类的名字,类的访问属性,类所属的包名等等。所以当打印Date.getClass()时打印出的就是Date的访问属性,Date的所属包名。

Class类的三种实例化方式:

1.对象.getClass();//取得Class对象
2.类名.class;//可以直接根据某个具体类来取得其Class对象
3.调用Class类的静态方法Class.forName(String className)传入类的全名称来取得其Class对象。
比如:Class<?> cls = Class.forName(“java.util.Date”);

使用:

Class<?> cls1 = date.getClass();
Class<?> cls = Class.forName("java.util.Date");
Class<?> cls2 = Date.class;

Class类对象可以通过反射实例化对象

方法:
public T newInstance() throws InstantiationException,IllegalAccessException

使用:
Object obj = cls.newInstance();
就相当于new了一个对象

Class类对象能干什么
得到Class对象,就可以根据对象获取到类中的变量,方法,构造等信息。获取这些信息有相应的方法。

反射与类的操作

取得类的包名称:public Package getPackage()
取得父类的Class对象:public native Class<? super T>getSuperclass();
取得实现的父接口:public Class<?>[] getInterfaces()

Class<?> cls = Watermelon.class;
System.out.println(cls.getPackage().getName());//包名
System.out.println(cls.getSuperclass().getName());//父类名
Class<?>[] str = cls.getInterfaces();
for(Class<?> str1:str){
    System.out.printf(str1.getName());//父接口名
}

反射调用类中构造方法

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

public Constructor getConstructor(Class<?>… parameterTypes) throws NoSuchMethodException, SecurityException
只能取得类中public权限的构造方法
public Constructor getDeclaredConstructor(Class<?>… parameterTypes)
可以取得类中全部构造方法,包含私有构造

取得类中所有构造方法

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

举例:

class Person{
    public Person(){};
    public Person(int n){ };
    public Person(String name,int age){};
    private Person(String name,String name1){};

}

public class Test{
    public static void main(String[] args) throws Exception {
        //1.取得Class类的对象
        Class<?> cls = Person.class;
        //取得类中所有public权限的构造
        System.out.println("getConstructors();取得类中所有public权限构造");
        Constructor<?>[] constructors = cls.getConstructors();
        for(Constructor<?> constructor : constructors){
            System.out.println(constructor);
        }

        //取得类中全部构造
        System.out.println("getDeclaredConstructors();取得类中所有构造");
        constructors = cls.getDeclaredConstructors();
        for(Constructor<?> constructor :constructors){
            System.out.println(constructor);
        }

        //取得类中指定参数构造,public权限
        System.out.println("getConstructor(String.class,int.class);取得指定参数的构造,public权限");
        Constructor<?> constructor = cls.getConstructor(String.class,int.class);
        System.out.println(constructor);

        //取得类中指定参数构造,所有权限
        System.out.println("getDeclaredConstructor(String.class,String.class);取得指定参数的构造,所有权限");
        constructor = cls.getDeclaredConstructor(String.class,String.class);
        System.out.println(constructor);
    }
}

结果:

getConstructors();取得类中所有public权限构造
public www.bit.java.Person(java.lang.String,int)
public www.bit.java.Person(int)
public www.bit.java.Person()
getDeclaredConstructors();取得类中所有构造
private www.bit.java.Person(java.lang.String,java.lang.String)
public www.bit.java.Person(java.lang.String,int)
public www.bit.java.Person(int)
public www.bit.java.Person()
getConstructor(String.class,int.class);取得指定参数的构造,public权限
public www.bit.java.Person(java.lang.String,int)
getDeclaredConstructor(String.class,String.class);取得指定参数的构造,所有权限
private www.bit.java.Person(java.lang.String,java.lang.String)

可以使用Constructor类实例化对象

class Person{
    private String name;
    private int age;
    public Person(String name,int age) {
        this.name = name;
        this.age = age;
    };

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Test{
    public static void main(String[] args) throws Exception {
        //1.取得Class类的对象
        Class<?> cls = Person.class;
        Constructor<?> constructor = cls.getConstructor(String.class,int.class);
        System.out.println(constructor.newInstance("abaka",21));
    }
}

结果:
Person{name=‘abaka’, age=21}

反射调用普通方法

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

public Method getMethod(String name, Class<?>… parameterTypes)
//方法有重载所以要传名称和参数类型取得本类以及父类中所有public方法
public Method getDeclaredMethod(String name, Class<?..parameterTypes)
取得本类中全部普通方法,包括私有方法

取得类中全部普通方法

public Method[] getMethods() throws SecurityException
取得本类以及父类中所有public方法
public Method[] getDeclaredMethods() throws SecurityException
取得本类中全部普通方法,包括私有方法

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

public Object invoke(Object obj, Object… args)//具体对象, 具体对象的值

//1.取得Class类的对象
Class<?> cls = Person.class;
//2.取得本类以及父类中所有public方法
Method[] methods = cls.getMethods();
for(Method method:methods){
    System.out.println(method);
}

应用:

class Person{
    private String name;
    private int age;
    public void setName(String name){
        this.name = name;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }


}

public class Test{
    public static void main(String[] args) throws Exception {
        //1.取得Class类的对象
        Class<?> cls = Person.class;
        //2.创建Person实例化对象
        Person person = (Person)cls.newInstance();
        //3.取得方法,拿到setName的Method对象
        Method method = cls.getMethod("setName",String.class);
        Method method1 = cls.getMethod("setAge", int.class);
        //4.通过invoke进行调用
        method.invoke(person,"abaka");
        method1.invoke(person,21);
        System.out.println(person);

    }
}

反射调用类中属性Filed
取得类中指定属性

public Field getField(String name)throws NoSuchFieldException, SecurityException
取得本类以及父类中所有public属性
public Field getDeclaredField(String name)throws NoSuchFieldException, SecurityException
取得本类中全部普通属性,包含私有属性。

取得类中全部属性

public Field[] getFields() throws SecurityException
public Field[] getDeclaredFields() throws SecurityException

设置属性

public void set(Object obj, Object value)

取得属性

public Object get(Object obj) throws IllegalArgumentException,IllegalAccexxException

取得属性的类型

public Class<?> getType()

使用:


//1.先创建class对象Class<?> cls = Person.class;
//2.创建Person实例化对象
Person person = (Person)cls.newInstance();
Field field = cls.getField("name");
field.set(person,"abaka");
System.out.println(field.get(person));


猜你喜欢

转载自blog.csdn.net/qq_39032310/article/details/84571202