转载请注明出处:https://blog.youkuaiyun.com/jiyisuifeng222/article/details/117702827
本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 情花打雪 即可关注,每个工作日都有文章更新。
本篇文章主要讲解Java反射中构造方法和继承关系相关操作:
-
获取构造方法
-
获取继承关系
-
isAssignableFrom()方法与instanceof关键字的区别
获取构造方法:
使用new操作符创建实例:
Student p = new Student();
通过反射创建新实例,可以调用Class提供的newInstance()方法:
Student p = Student.class.newInstance();
调用Class.newInstance()的局限是,它只能调用该类的public无参数构造方法。
如果构造方法带有参数,或者不是public,就无法直接通过Class.newInstance()来调用。
为了调用任意的构造方法,Java的反射API提供了Constructor对象,它包含一个构造方法的所有信息,可以创建一个实例。
Constructor对象和Method非常类似,不同之处仅在于它是一个构造方法,并且,调用结果总是返回实例.示例如下
public class MainTestDemo {
public static void main(String[] args) throws Exception {
// 获取构造方法Integer(int):
Constructor constructor1 = Integer.class.getConstructor(int.class);
// 调用构造方法:
Integer integer = (Integer) constructor1.newInstance(123);
System.out.println(integer);
// 获取构造方法Integer(String)
Constructor constructor2 = Integer.class.getConstructor(String.class);
Integer n2 = (Integer) constructor2.newInstance("888");
System.out.println(n2);
}
}
通过Class实例获取Constructor的方法总结如下:
- getConstructor(Class...):获取某个public的Constructor;//
- getDeclaredConstructor(Class...):获取某个Constructor;
- getConstructors():获取所有public的Constructor;
- getDeclaredConstructors():获取所有Constructor。
注意:Constructor
总是当前类定义的构造方法,和父类无关,因此不存在多态的问题。
调用非public
的Constructor
时,必须首先通过setAccessible(true)
设置允许访问。setAccessible(true)
可能会失败。
获取继承关系
通过Class对象可以获取继承关系:
- 1.Class getSuperclass():获取父类类型;(单继承)
- 2.Class[] getInterfaces():获取当前类实现的所有接口;(多实现)
- 3.通过Class对象的isAssignableFrom()方法,判断Class向上转型是否可以实现。
1.获取父类类型
public class MainTestDemo {
public static void main(String[] args) throws Exception {
Class i = Integer.class;
Class n = i.getSuperclass();
System.out.println(n);
Class o = n.getSuperclass();
System.out.println(o);
System.out.println(o.getSuperclass());
}
}
输出:
class java.lang.Number
class java.lang.Object
null
Integer的父类类型是Number,Number的父类是Object,Object的父类是null。除Object外,其他任何非interface的Class都必定存在一个父类类型。
2.获取当前类实现的所有接口
public class MainTestDemo {
public static void main(String[] args) throws Exception {
Class s = Integer.class;
Class[] is = s.getInterfaces();
for (Class i : is) {
System.out.println(i);
}
}
}
输出Integer实现的接口有:
java.lang.Comparable
java.lang.constant.Constable
java.lang.constant.ConstantDesc
要特别注意:getInterfaces()
只返回当前类直接实现的接口类型,并不包括其父类实现的接口类型。
此外,对所有interface
的Class
调用getSuperclass()
返回的是null
,获取接口的父接口要用getInterfaces()
System.out.println(java.io.DataInputStream.class.getSuperclass()); // java.io.FilterInputStream,因为DataInputStream继承自FilterInputStream
System.out.println(java.io.Closeable.class.getSuperclass()); // null,对接口调用getSuperclass()总是返回null,获取接口的父接口要用getInterfaces()
如果一个类没有实现任何interface
,那么getInterfaces()
返回空数组。
3.判断Class向上转型
在非反射调用中,当我们判断一个实例是否是某个类型时,正常情况下,使用instanceof操作符:
Object n = Integer.valueOf(123);
boolean isDouble = n instanceof Double; // false
boolean isInteger = n instanceof Integer; // true
boolean isNumber = n instanceof Number; // true
boolean isSerializable = n instanceof java.io.Serializable; // true
如果是两个Class实例,要判断一个向上转型是否成立,可以调用isAssignableFrom():
// Integer i = ?
Integer.class.isAssignableFrom(Integer.class); // true,因为Integer可以赋值给Integer
// Number n = ?
Number.class.isAssignableFrom(Integer.class); // true,因为Integer可以赋值给Number
// Object o = ?
Object.class.isAssignableFrom(Integer.class); // true,因为Integer可以赋值给Object
// Integer i = ?
Integer.class.isAssignableFrom(Number.class); // false,因为Number不能赋值给Integer
isAssignableFrom()方法与instanceof关键字的区别
总结为以下两个点:
isAssignableFrom()方法是从类继承的角度去判断,instanceof关键字是从实例继承的角度去判断。
isAssignableFrom()方法是判断是否为某个类的父类,instanceof关键字是判断是否某个类的子类。
使用方法:
父类.class.isAssignableFrom(子类.class)
子类实例 instanceof 父类类型
isAssignableFrom()方法的调用者和参数都是Class对象,调用者为父类,参数为本身或者其子类。
instanceof关键字两个参数,前一个为类的实例,后一个为其本身或者父类的类型。
关注我的技术公众号,每天都有优质技术文章推送。
微信扫一扫下方二维码即可关注: