Java拾贝第十七天——反射之初认Class类

发布时间 2023-11-05 18:19:13作者: ocraft

反射

反射可以在运行中知晓任意类的任意属性和方法。这种动态获取信息的功能称之为反射

小栗子

package moudle2;

public class Test17 {
    public static void main(String[] args) {
        Test17 t17 = new Test17();
        System.out.println(t17.getClass());
    }
}

程序运行结果:

class moudle2.Test17

上述栗子中,Test17类使用了继承自Object类的getClass()方法。

打印结果是Test17类的完整的 "包.类" 名。(也叫完整名称)

getClass()方法定义如下:

public final native Class<?> getClass()

final:无法被子类重写的方法。
native:调用底层类库,底层使用其他语言实现。
返回类型:Class,一个名为Class的类。
泛型:通配符,接收任意类型。

认识Class类

getClass()方法返回的是一个Class类,Class类是Java反射的源头。

Class类表示一个类自身,通过Class类可以完整地获得一个类的完整结构,包括:方法,属性,完整名称,甚至包括其父类和实现的接口。

三种实例化Class类对象的方法

栗子:

package moudle2;

public class Test17 {
    public static void main(String[] args) throws ClassNotFoundException {
        Test17 t17 = new Test17();

        System.out.println(Class.forName("moudle2.Test17"));//Class类的静态方法,传参为完整类名
        System.out.println(t17.getClass());//继承自Object的getClass()方法
        System.out.println(Test17.class);//一种特殊的实例化 类.class
    }
}

程序运行结果:

class moudle2.Test17
class moudle2.Test17
class moudle2.Test17

上述三种方法都是一样的,但第一种Class.forName()的方式较为常见且更具灵活性。

但可能会出现ClassNotFoundException异常

Class类的使用

Clss类的部分常用方法:

方法 类型 描述
public static Class<?> forName(String className) throws ClassNotFoundException 静态方法 传入完整类名返回实例化Class对象
public String getName() 普通方法 获取一个类的完整名称
public T newInstance() throws InstantiationException, IllegalAccessException 普通方法 返回Class定义的类实例化对象
public Class<?>[] getInterfaces() 普通方法 获取一个类实现的全部接口
public native Class<? super T> getSuperclass() 底层方法 获取一个类的父类

public String getName()

获取一个类的完整名称

栗子:

package moudle2;

public class Test17 {
    public static void main(String[] args) throws ClassNotFoundException {
        Test17 t17 = new Test17();
        System.out.println(Class.forName("moudle2.Test17").getName());
    }
}

程序运行结果:

moudle2.Test17

public T newInstance()

创建并返回一个类的实例化对象

栗子:

package moudle2;

public class Test17 {
    public static void main(String[] args) {
        try {
            Class clazz = Class.forName("moudle2.Noodle");//完整名称
            Noodle o = (Noodle) clazz.newInstance();//创建Noodle类的实例 等价于 Noodle o =new Noodle();
            o.eat();//向下转型是为了调用Noodle类的特有方法 eat
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class Noodle {
    private String name = "面条";

    public Noodle() {
    }
    public void eat() {
        System.out.println("吃" + name);
    }
}

程序运行结果:

吃面条

注意被实例化的类必须存在无参构造。(隐式显式都可以,但必须存在无参构造)

不存在无参构造的栗子如下:

package moudle2;

public class Test17 {
    public static void main(String[] args) {
        try {
            Class clazz = Class.forName("moudle2.Noodle");
            Noodle o = (Noodle) clazz.newInstance();//创建Noodle类的实例 等价于 Noodle o =new Noodle();
            o.eat();//向下转型是为了调用Noodle类的特有方法 eat

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class Noodle {
    private String name = "面条";

    public Noodle(String name) {//显式定义了有参构造,默认的隐式无参构造被覆盖
        this.name = name;
    }
    public void eat() {
        System.out.println("吃" + name);
    }
}

程序运行结果:

java.lang.InstantiationException: moudle2.Noodle
	at java.lang.Class.newInstance(Class.java:427)
	at moudle2.Test17.main(Test17.java:7)
Caused by: java.lang.NoSuchMethodException: moudle2.Noodle.<init>()
	at java.lang.Class.getConstructor0(Class.java:3082)
	at java.lang.Class.newInstance(Class.java:412)
	... 1 more

因此,建议每个自定义的类必须显式定义无参构造

public Class<?>[] getInterfaces()

获取一个类实现的所有接口

栗子:

package moudle2;

public class Test17 {
    public static void main(String[] args) {
        try {
            Class clazz = Class.forName("moudle2.Noodle");

            Class[] interfaces = clazz.getInterfaces();
            for (Class a : interfaces) {
                System.out.println(a);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class Noodle implements Hot,Delicious,Cheap {}

interface Hot{}
interface Delicious{}
interface Cheap{}

程序运行结果:

interface moudle2.Hot
interface moudle2.Delicious
interface moudle2.Cheap

public native Class<? super T> getSuperclass()

获取一个类的父类

栗子:

package moudle2;

public class Test17 {
    public static void main(String[] args) {
        try {
            Class clazz = Class.forName("moudle2.Noodle");

            Class a = clazz.getSuperclass();
            System.out.println(a);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class Noodle extends Rice {}

class Rice {}

程序运行结果:

class moudle2.Rice