目录
1.1 、直接通过一个 class 的静态变量class获取
1.2、如果有一个实例变量,通过该实例变量提供的 getClasss() 方法获取
1.3、知道一个 class 的完整类名,通过Class.forName()获取
通过 Class 实例获取 class 信息的方法称为反射(Reflection)。
由于 JVM 为每个加载的类创建了对应的类实例,并在实例中保存了该类的所有信息,包括类名、包名、父类、实现的接口、所有方法、字段等。因此,如果获得了某个类实例,就可以通过这个类实例取到实例对应的类的所有信息。
一、获取 Class 实例
获取一个 class 的 Class 实例三种方法:
1.1 、直接通过一个 class 的静态变量class获取
Class clazz = String.class;
1.2、如果有一个实例变量,通过该实例变量提供的 getClasss() 方法获取
如果有一个实例变量,可以通过该实例变量提供的 getClass() 方法获取
String str = "hello world";
Class clazz = str.getClass();
1.3、知道一个 class 的完整类名,通过
Class.forName()
获取
Class.forName()
Class clazz = Class.forName("java.lang.String");
因为Class实例在JVM中是唯一的,所以,上述方法获取的Class实例是同一个实例。可以用==比较两个Class实例:
public class Main {
public static void main(String[] args) throws Exception {
Class clazz1 = String.class;
String str = "Hello world";
Class clazz2 = str.getClass();
Class clazz3 = Class.forName("java.lang.String");
System.out.println(clazz1 == clazz2); //true
System.out.println(clazz1 == clazz3); //true
System.out.println(clazz2 == clazz3);//true
}
}
class 实例比较和 instanceof 的差别:
public class Main {
public static void main(String[] args) throws Exception {
Integer n = new Integer(123);
boolean b1 = n instanceof Integer; // true,因为n是Integer类型
boolean b2 = n instanceof Number; // true,因为n是Number类型的子类
boolean b3 = n.getClass() == Integer.class; // true,因为n.getClass()返回Integer.class
boolean b4 = n.getClass() == Number.class; // false,因为Integer.class!=Number.class
}
}
用 instanceof 不但匹配指定类型,还匹配指定类型的子类,而用 == 判断class 实例可以精确地判断数据类型,但不能作为比较子类型比较。
通常情况,用 instanceof 判断数据类型,应为面向抽象编程地时候,不关心具体地子类型。只有在需要精确判断一个类型是不是某个 class 的时候,才使用 == 判断 class 实例。
反射的目的是为了获取某个实例的信息,因为当拿到某个 object 实例时,可以通过反射获取 object 的 class 信息。
例如获取到一个 Class 实例 ,就可以通过该 Class 实例来创建对应类型的实例:
public class Main {
public static void main(String[] args) throws Exception{
// 获取String的Class实例:
Class cls = String.class;
// 创建一个String实例:
String s = (String) cls.newInstance();
}
}
上述代码相当于 new String()。 通过 Class.newInstance 可以创建实例,它的局限性是只能调用 public 的无参构造方法。带参数的构造方法或者非 public 的构造方法都无法通过 Class.newInstance() 被调用。
动态加载
JVM 在执行 Java 程序的时候,并不是一次性把所有用到的 class 全部加载到内存,而是第一次需要用到 class 时才加载。例如:
// Main.java
public class Main {
public static void main(String[] args) {
if (args.length > 0) {
create(args[0]);
}
}
static void create(String name) {
Person p = new Person(name);
}
}
当执行Main.java 时,由于用到 Main, JVM会把 Main.class 加载到内存。然后,并不会加载 Person.class ,除非程序执行到 create() 方法, JVM 发现需要加载 Person 类时,才会首次加载 Person.class 。如果没有加载 create() 方法,那么 Person.class 就不会被加载。这就是 JVM 动态加载 class 的特性。
Class 类扩展方法
方法 |
描述 |
String toGenericString() | 返回一个描述这个类的字符串信息,包含修饰符和类型参数的信息 |
forName(String className) | 根据类的完整路径返回Class对象 |
forName(String name, boolean initialize,ClassLoader loader) | 根据类的完整路径返回Class对象 |
T newInstance() | 创建类的实例 |
boolean isInstance(Object obj) | 判断是否是类的实例 |
boolean isAssignableFrom(Class<?> cls) | 判断当前的Class对象所表示的类,是不是参数中传递的Class对象所表示的类的父类 |
boolean isInterface() | 判断是否接口 |
boolean isPrimitive() | 判断是否为原始基本类型(例如int、char、long..) |
boolean isAnnotation() | 判断是否注解类型 |
boolean isSynthetic() |
判断是的合成类 |
String getName() | 获取类名称 |
getClassLoader() | 获取加载器 |
Class<? super T> getSuperclass() | 获取父类 |
Type getGenericSuperclass() | 获取直接父类,并且父类的泛型类型也会返回 |
Package getPackage() | 获取包名 |
Class<?>[] getInterfaces() | 获得这个对象所实现的所有接口 |
Type[] getGenericInterfaces() | 获得这个对象所实现的所有接口并且返回接口泛型 |
Class<?> getComponentType() | 获取一个数组的Class对象 |
int getModifiers() | 获取修饰符 |
Object[] getSigners() | 返回类的签名者 |
Method getEnclosingMethod() | 当此Class对象表示方法内部的本地或匿名类时,使用getEnclosingMethod()方法返回基础类的最新封闭方法 |
Constructor<?> getEnclosingConstructor() | 如果此类是在该构造函数中声明的本地类或匿名类,则方法返回此类的封闭构造函数 |
Class<?> getDeclaringClass() | 返回表示在它被声明的类的Class对象,如果此Class对象所表示的类或接口是另一个类成员 |
Class<?> getEnclosingClass() | 返回底层的直接外围类。如果底层类是顶级类(Object)则返回null |
String getSimpleName() | 获取简单类名 |
String getCanonicalName() | 获取规范名称 |
boolean isAnonymousClass() | 判断是否匿名内部类 |
boolean isLocalClass() | 判断是否为本地类 |
boolean isMemberClass() | 判断是否成员类 |
Class<?>[] getClasses() | 返回Class 对象数组(不包含private修饰) |
Field[] getFields() | 返回公共字段(public 修饰) |
Method[] getMethods() | 返回公共方法(public 修饰) |
Constructor<?>[] getConstructors() | 获取构造方法(public 修饰) |
Field getField(String name) | 根据参数获取字段信息(public 修饰) |
Method getMethod(String name, Class<?>… parameterTypes) | 返回Method对象匹配指定名称和parameterTypes(public 修饰) |
Constructor<T> getConstructor(Class<?>… parameterTypes) | 返回一个 Constructor 对象,该对象反映了此 Class 对象表示的类的指定公共构造函数 |
Class<?>[] getDeclaredClasses() | 返回Class 对象数组 |
Field[] getDeclaredFields() | 获取类字段信息 |
Method[] getDeclaredMethods() | 获取类方法 |
Constructor<?>[] getDeclaredConstructors() | 获取构造方法 |
Field getDeclaredField(String name) | 根据参数获取字段信息 |
Method getDeclaredMethod(String name, Class<?>… parameterTypes) | 返回Method对象匹配指定名称和parameterTypes |
Constructor<T> getDeclaredConstructor(Class<?>… parameterTypes) | 根据参数获取对应构造方法 |
InputStream getResourceAsStream(String name) | 查找具有给定名称的资源 |
java.net.URL getResource(String name) | 查找具有给定名称的资源,返回URL |
java.security.ProtectionDomain getProtectionDomain() | 返回类的 ProtectionDomain 对象 |
boolean desiredAssertionStatus() | 该方法以布尔值的形式返回该类的指定断言状态 |
boolean isEnum() | 判断是否枚举 |
T[] getEnumConstants() | 获取枚举元素 |
T cast(Object obj) | 将对象强制转换为所表示的类或接口 |
<U> Class<? extends U> asSubclass(Class<U> clazz) | 强制把Class对象转化成参数类的子类 |
AnnotatedType getAnnotatedSuperclass() | 获取当前类的父类,可以用 AnnotatedType 来描述,也就是说它们申明了泛型并且被注解标注 |
AnnotatedType[] getAnnotatedInterfaces() | 获取当前类的接口,可以用 AnnotatedType[] 来描述,也就是说它们申明了泛型并且被注解标 |
示例
import com.sun.javafx.geom.transform.Identity;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.security.ProtectionDomain;
import java.util.HashMap;
public class Main {
public Integer age;
private String userName;
public Main() {
}
private Main(Integer age, String userName) {
this.age = age;
this.userName = userName;
}
public void showLong(Long l) {
}
private void say(Long l) {
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Main{" +
"userName='" + userName + '\'' +
'}';
}
public static void main(String[] args) {
printClassInfo();
}
static void printClassInfo() {
//返回一个描述这个类的字符串信息,包含修饰符和类型参数的信息
toGenericString();
//根据类的完整路径,加载类,返回Class对象
clssForName();
//创建类的实例
newInstance();
// 判断是否是类的实例
isInstance();
//判断当前的Class对象所表示的类,是不是参数中传递的Class对象所表示的类的父类
isAssignableFrom();
// 判断是否接口
isInterface();
// 判断是否数组
isArray();
//判断是否为原始基本类型(例如int、char、long..)
isPrimitive();
// 判断是否注解类型
isAnnotation();
/**
* 判断是的合成类
* https://blog.sina.com.cn/s/blog_1534f339a0102y88n.html
*
*/
// 获取类名称
getName();
// 获取加载器
getClassLoader();
// 获取父类(public 修饰)
getSuperclass();
// 获取直接父类,并且父类的泛型类型也会返回
getGenericSuperclass();
// 获取包名
getPackage();
// 获得这个对象所实现的所有接口
getInterfaces();
// 获得这个对象所实现的所有接口并且返回接口泛型
getGenericInterfaces();
// 获取一个数组的Class对象
getComponentType();
// 获取修饰符
getModifiers();
// 返回类的签名者
getSigners();
// 当此Class对象表示方法内部的本地或匿名类时,使用getEnclosingMethod()方法返回基础类的最新封闭方法
getEnclosingMethod();
// 如果此类是在该构造函数中声明的本地类或匿名类,则方法返回此类的封闭构造函数
getEnclosingConstructor();
//返回表示在它被声明的类的Class对象,如果此Class对象所表示的类或接口是另一个类成员
getDeclaringClass();
// 返回底层的直接外围类。如果底层类是顶级类(Object)则返回null
getEnclosingClass();
// 获取简单类名
getSimpleName();
// 获取规范名称
getCanonicalName();
// 判断是否匿名内部类
isAnonymousClass();
// 判断是否为本地类
isLocalClass();
// 判断是否成员类
isMemberClass();
// 返回Class 对象数组(不包含private修饰)
getClasses();
//返回公共字段(public 修饰)
getFields();
//返回公共方法(public 修饰)
getMethods();
// 获取构造方法(public 修饰)
getConstructors();
// 根据参数获取字段信息(public 修饰)
getField();
//返回Method对象匹配指定名称和parameterTypes(public 修饰)
getMethod();
//返回一个 Constructor 对象,该对象反映了此 Class 对象表示的类的指定公共构造函数
getConstructor();
//返回Class 对象数组
getDeclaredClasses();
// 获取类字段信息
getDeclaredFields();
//获取类方法
getDeclaredMethods();
// 获取构造方法
getDeclaredConstructors();
// 根据参数获取字段信息
getDeclaredField();
// 返回Method对象匹配指定名称和parameterTypes
getDeclaredMethod();
// 根据参数获取对应构造方法
getDeclaredConstructor();
// 查找具有给定名称的资源
getResourceAsStream();
// 查找具有给定名称的资源,URL
getResource();
//返回类的 ProtectionDomain 对象
getProtectionDomain();
//该方法以布尔值的形式返回该类的指定断言状态
desiredAssertionStatus();
// 判断是否枚举
isEnum();
// 获取枚举元素
getEnumConstants();
//将对象强制转换为所表示的类或接口
cast();
//强制把Class对象转化成参数类的子类
asSubclass();
// 获取当前类的父类,可以用 AnnotatedType 来描述,也就是说它们申明了泛型并且被注解标注
getAnnotatedSuperclass();
//获取当前类的接口,可以用 AnnotatedType[] 来描述,也就是说它们申明了泛型并且被注解标注
getAnnotatedInterfaces();
}
//返回一个描述这个类的字符串信息,包含修饰符和类型参数的信息
static void toGenericString() {
Class clazz = Runnable.class;
System.out.println("toGenericString: " + clazz);
}
// 根据类的完整路径返回与类或关联的Class对象
static void clssForName() {
try {
// 参数:类的完整路
Class clazz1 = Class.forName("Main");
ClassLoader cLoader = clazz1.getClassLoader();
/**
* 参数一:类的完整路
* 参数二 类是否初始化 true:初始化 false 不初始化
* 参数三:加载器
*/
Class clazz2 = Class.forName("java.lang.String", true, cLoader);
System.out.println("Class.forName():" + clazz1);
System.out.println("Class.forName(...):" + clazz2);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// 创建类的实例
static void newInstance() {
try {
Class clazz = Main.class;
// 创建Main类的实例
Main main = (Main) clazz.newInstance();
main.setUserName("张三");
System.out.println("newInstance: " + main.toString());
} catch (Exception e) {
}
}
// 判断是否属于类的实例
static void isInstance() {
try {
Class clazz = Class.forName("Main");
Class clazz1 = Class.forName("java.lang.String");
// 创建Main类的实例
Main main = (Main) clazz.newInstance();
// 判断是否是类的实例
boolean result = clazz.isInstance(main); // true
boolean result1 = clazz1.isInstance(main); // false
System.out.println("isInstance: result = " + result + " result1=" + result1);
} catch (Exception e) {
}
}
// 判断当前的Class对象所表示的类,是不是参数中传递的Class对象所表示的类的父类
static void isAssignableFrom() {
try {
Class parent = Class.forName("Parent");
Class Son = Class.forName("Son");
//
Boolean result = parent.isAssignableFrom(Son); // true
System.out.println("isAssignableFrom: result = " + result);
} catch (Exception e) {
}
}
// 判断是否接口
static void isInterface() {
try {
Class demoService = Class.forName("DemoService");
Boolean result = demoService.isInterface();
System.out.println("isInterface: result = " + result);// true
} catch (Exception e) {
}
}
// 判断是否数组
static void isArray() {
Class clazz = String[].class;
Boolean result = clazz.isArray();
System.out.println("isInterface: result = " + result); // true
}
// 判断是否为原始基本类型(例如int、char、long..)
static void isPrimitive() {
String str = new String();
Class cl1 = str.getClass();
//创建并返回short-
// short sh = 10;
Class cl2 = short.class; // true
// Class cl2 = Integer.class; // false
Boolean result = cl1.isPrimitive(); //false
Boolean result1 = cl2.isPrimitive(); //true
System.out.println("isPrimitive: result = " + result + " result1 = " + result1);
}
// 判断是否注解类型
static void isAnnotation() {
Class ann1 = Identity.class;
Class ann2 = Deprecated.class;
System.out.println("isAnnotation ann1= " + ann1.isAnnotation() + " ann2=" + ann2.isAnnotation());
}
//获取类名称
static void getName() {
Class clazz = Main.class;
System.out.println("getName = " + clazz.getName());
}
// 获取类加载器
static void getClassLoader() {
Class clazz = Main.class;
System.out.println("getClassLoader = " + clazz.getClassLoader());
}
// 获取父类
static void getSuperclass() {
Class clazz = Son.class;
System.out.println("getSuperclass = " + clazz.getSuperclass());
}
// 获取直接父类
static void getGenericSuperclass() {
Class clazz = Son.class;
System.out.println("getGenericSuperclass = " + clazz.getGenericSuperclass());
}
// 获取包名
static void getPackage() {
Class clazz = String.class;
System.out.println("getPackage = " + clazz.getPackage());
}
// 获得这个对象所实现的所有接口
static void getInterfaces() {
Class clazz = DemoServiceImpl.class;
Class[] arr = clazz.getInterfaces();
if (null != arr && arr.length > 0) {
System.out.println("getInterfaces arr = " + arr[0]);
}
}
// 获得这个对象所实现的所有接口并且返回接口泛型
static void getGenericInterfaces() {
Class clazz = DemoServiceImpl.class;
Type[] arr = clazz.getGenericInterfaces();
if (null != arr && arr.length > 0) {
System.out.println("getGenericInterfaces arr = " + arr[0]);
}
}
// 获取一个数组的Class对象
static void getComponentType() {
Class clazz = String[].class;
Class componentType = clazz.getComponentType();
Class clazz1 = String.class;
Class componentType1 = clazz1.getComponentType();
System.out.println("getComponentType = " + componentType + " getComponentType=" + componentType1);
}
// 获取修饰符
static void getModifiers() {
Class clazz = Main.class;
int modifiers = clazz.getModifiers();
System.out.println("getModifiers = " + modifiers);
}
// 返回类的签名者
static void getSigners() {
try {
Class cls = Main.class;
Object[] obj = cls.getSigners();
System.out.println("getSigners = " + obj);
} catch (Exception ex) {
System.out.println(ex.toString());
}
}
// 当此Class对象表示方法内部的本地或匿名类时,使用getEnclosingMethod()方法返回基础类的最新封闭方法
static void getEnclosingMethod() {
try {
Class c = (new Out()).ClassAObject().getClass();
System.out.println("getEnclosingMethod() = " + c.getEnclosingMethod());
} catch (Exception ex) {
System.out.println(ex.toString());
}
}
// 如果此类是在该构造函数中声明的本地类或匿名类,则方法返回此类的封闭构造函数
static void getEnclosingConstructor() {
try {
Class c = (new Out()).c.getClass();
System.out.println("getEnclosingConstructor() = " + c.getEnclosingConstructor());
} catch (Exception ex) {
System.out.println(ex.toString());
}
}
// 返回这个类的声明类。
static void getDeclaringClass() {
Class cl = Integer.class;
// It returns an array of Methods
// that denotes the private, protected, public and default
// Methods of the class Integer
Method[] methods = cl.getMethods();
// Traverse Integer class
// for (int i = 0; i < methods.length; ++i) {
Class declare_classes = methods[0].getDeclaringClass();
System.out.println(" getDeclaringClass= " + declare_classes.toString());
// }
}
/**
* 返回底层直接外围类
*/
static void getEnclosingClass() {
Class clazz = new Out().c.getClass();
Class clazz1 = Object.class;
System.out.println(" getEnclosingClass= " + clazz.getEnclosingClass());
System.out.println(" getEnclosingClass= " + clazz1.getEnclosingClass());
}
// 获取简单类名
static void getSimpleName() {
Class clazz = String.class;
System.out.println(" getSimpleName= " + clazz.getSimpleName());
}
// 获取规范名称
static void getCanonicalName() {
Class clazz = String.class;
System.out.println(" getCanonicalName= " + clazz.getCanonicalName());
}
// 判断是否匿名类
static void isAnonymousClass() {
Class clazz = new HashMap<String, String>() {
// 匿名类
}.getClass();
System.out.println(" isAnonymousClass= " + clazz.isAnonymousClass());
}
// 判断是否为本地类
static void isLocalClass() {
class A {
}
Class clazz = A.class;
Class clazz1 = Out.class;
System.out.println(" isLocalClass= " + clazz.isLocalClass() + " isLocalClass=" + clazz1.isLocalClass());
}
// 判断是否成员类
static void isMemberClass() {
class A {
}
Class clazz = A.class;
Class clazz1 = Out.class;
System.out.println(" isMemberClass= " + clazz.isLocalClass() + " isMemberClass=" + clazz1.isLocalClass());
}
// 返回Class 对象数组
static void getClasses() {
Class clazz = Main.class;
Class[] clazzArr = clazz.getClasses();
for (int i = 0; i < clazzArr.length; i++) {
System.out.println("getClasses = " + clazzArr[i].getName());
}
}
// 返回公共字段(public 修饰)
static void getFields() {
Class clazz = Main.class;
Field[] clazzArr = clazz.getFields();
for (int i = 0; i < clazzArr.length; i++) {
System.out.println("getFields = " + clazzArr[i]);
}
}
// 返回公共方法(public 修饰)
static void getMethods() {
Class clazz = Main.class;
Method[] clazzArr = clazz.getMethods();
for (int i = 0; i < clazzArr.length; i++) {
System.out.println("getMethods = " + clazzArr[i]);
}
}
// 获取构造方法
static void getConstructors() {
Class clazz = Main.class;
Constructor[] clazzArr = clazz.getConstructors();
for (int i = 0; i < clazzArr.length; i++) {
System.out.println("getConstructors = " + clazzArr[i]);
}
}
// 根据参数获取字段信息,不包含(private 修饰)
static void getField() {
try {
Class clazz = Main.class;
Field field = clazz.getField("age");
System.out.println("getField=" + field);
} catch (Exception e) {
}
}
// 返回Method对象匹配指定名称和parameterTypes
static void getMethod() {
try {
Class clazz = Main.class;
Class[] cArg = new Class[1];
cArg[0] = Long.class;
Method method = clazz.getMethod("showLong", cArg);
System.out.println("getMethod=" + method.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
//返回一个 Constructor 对象,该对象反映了此 Class 对象表示的类的指定公共构造函数
static void getConstructor() {
try {
Class cls[] = new Class[]{String.class};
Constructor c = String.class.getConstructor(cls);
System.out.println("getConstructor=" + c);
} catch (Exception e) {
e.printStackTrace();
}
}
// 返回Class 对象数组
static void getDeclaredClasses() {
Class clazz = Main.class;
Class[] clazzArr = clazz.getDeclaredClasses();
for (int i = 0; i < clazzArr.length; i++) {
System.out.println("getDeclaredClasses = " + clazzArr[i].getName());
}
}
//获取类字段信息
static void getDeclaredFields() {
try {
Class clazz = Main.class;
Field[] fieldArr = clazz.getDeclaredFields();
for(Field f : fieldArr){
System.out.println("getDeclaredFields=" + f);
}
} catch (Exception e) {
}
}
// 获取类方法
static void getDeclaredMethods() {
try {
Class clazz = Main.class;
Method[] methodArr = clazz.getDeclaredMethods();
for(Method m : methodArr){
System.out.println("getDeclaredMethods=" + m);
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取构造方法
static void getDeclaredConstructors() {
try {
Constructor[] cArr= Main.class.getDeclaredConstructors();
for(Constructor c : cArr){
System.out.println("getDeclaredConstructors=" + c);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//根据参数获取字段信息
static void getDeclaredField() {
try {
Class clazz = Main.class;
Field field = clazz.getDeclaredField("userName");
System.out.println("getDeclaredField=" + field);
} catch (Exception e) {
}
}
// 返回Method对象匹配指定名称和parameterTypes
static void getDeclaredMethod() {
try {
Class clazz = Main.class;
Class[] cArg = new Class[1];
cArg[0] = Long.class;
Method method = clazz.getDeclaredMethod("say", cArg);
System.out.println("getDeclaredMethod=" + method.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
// 根据参数获取对应构造方法
static void getDeclaredConstructor() {
try {
Class parameterTypes[] = {Integer.class,String.class};
Constructor c = Main.class.getDeclaredConstructor(parameterTypes);
System.out.println("getDeclaredConstructor=" + c);
} catch (Exception e) {
e.printStackTrace();
}
}
// 查找具有给定名称的资源,返回InputStream
static void getResourceAsStream() {
InputStream in = Main.class.getResourceAsStream("application.properties");
byte[] buf = new byte[1024];
int len;
try {
while ((len = in.read(buf)) != -1) {
String s = new String(buf, 0,len,"GBK");
System.out.println(s);
}
in.close();
}catch (Exception E){
}
}
// 查找具有给定名称的资源,返回URL
static void getResource() {
java.net.URL url = Main.class.getResource("application.properties");
System.out.println("getResource = "+url);
}
// 返回类的 ProtectionDomain 对象
static void getProtectionDomain() {
ProtectionDomain protectionDomain = Main.class.getProtectionDomain();
System.out.println("getProtectionDomain = "+protectionDomain);
}
// 该方法以布尔值的形式返回该类的指定断言状态
static void desiredAssertionStatus() {
boolean result = Main.class.desiredAssertionStatus();
System.out.println("desiredAssertionStatus = "+result);
}
// 判断是否枚举
static void isEnum() {
boolean result = Main.class.isEnum();
boolean result1 = EnumDemo.class.isEnum();
System.out.println("isEnum = "+result +" isEnum="+result1);
}
// 获取枚举元素
static void getEnumConstants() {
EnumDemo[] enumDemoArr = EnumDemo.class.getEnumConstants();
for(EnumDemo e:enumDemoArr){
System.out.println("getEnumConstants = "+e );
}
}
//将对象强制转换为所表示的类或接口
static void cast() {
Class clazz = Main.class;
try {
Object obj =new Main(23,"张三");
if(obj instanceof Main){
Main m = (Main) clazz.cast(obj);
System.out.println("cast = "+m.toString() );
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 强制把Class对象转化成参数类的子类
static void asSubclass() {
Class son = Son.class;
Class parent = Parent.class;
try {
Class p = son.asSubclass(parent);
System.out.println("asSubclass ="+p);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取Class 类的父类注解
static void getAnnotatedSuperclass() {
try {
Annotation[] anns = B.class.getAnnotatedSuperclass().getAnnotations();
for (Annotation a : anns){
System.out.println("getAnnotatedSuperclass = "+a.annotationType().getName());
}
}catch (Exception e) {
e.printStackTrace();
}
}
//返回一个AnnotatedType对象数组,表示使用类型来指定此Class对象表示的实体的超接口
static void getAnnotatedInterfaces() {
try {
AnnotatedType[] anns = First.class.getAnnotatedInterfaces();
for (AnnotatedType a : anns){
System.out.println("getAnnotatedInterfaces = "+ a);
}
}catch (Exception e) {
e.printStackTrace();
}
}
public class a {
}
public class b {
}
private class c {
}
}
class Out {
public Object c;
public Out() {
class ClassA {
}
;
c = new ClassA();
}
public Object ClassAObject() {
class ClassA {
}
return new ClassA();
}
}
enum EnumDemo {
PAY_WX(),
PAY_ALI();
}
class Grandfather {
}
class Parent<T> extends Grandfather {
}
class Son extends Parent<Integer> {
}
interface DemoService<T> {
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface First { }
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface Second { }
class A { }
class B extends @First @Second A { }
class DemoServiceImpl implements DemoService<Integer> {
}
二、访问字段
Class 类提供了以下几个方法获取字段:
- Field getField(name):根据字段名获取某个public的field(包括父类)
- Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
- Field[] getFields():获取所有public的field(包括父类)
- Field[] getDeclaredFields():获取当前类的所有field(不包括父类)
示例
public class Main {
public static void main(String[] args) throws Exception {
Class stdClass = Student.class;
// 获取public字段"score":
System.out.println(stdClass.getField("score"));
// 获取继承的public字段"name":
System.out.println(stdClass.getField("name"));
// 获取private字段"grade":
System.out.println(stdClass.getDeclaredField("grade"));
}
}
class Student extends Person {
public int score;
private int grade;
}
class Person {
public String name;
}
控制台显示
public int Student.score
public java.lang.String Person.name
private int Student.grade
一个 Field 对象包含了一个字段的所有信息:
getName() : 返回字段名称 。例如 “name”。
getType(): 返回字段类型,也是一个 Class 示例。 例如 String.class。
getModifiers():返回字段修饰符,它是一个 int值,不同 bit 表示不同含义。
例如 String类的value字段为例,它的定义是:
public final class String {
private final byte[] value;
}
用反射获取该字段的信息,代码如下:
import java.lang.reflect.Modifier;
public class Main {
public static <Field> void main(String[] args) throws Exception {
java.lang.reflect.Field f = String.class.getDeclaredField("value");// private final char value[];
f.getName(); // "value"
f.getType(); // class [B 表示byte[]类型
int m = f.getModifiers();
Modifier.isFinal(m); // true
Modifier.isPublic(m); // false
Modifier.isProtected(m); // false
Modifier.isPrivate(m); // true
Modifier.isStatic(m); // false
}
}
获取/设置字段值
import java.lang.reflect.Field;
public class Main {
public static void main(String[] args) throws Exception {
Person p = new Person("Xiao Ming");
Class c = p.getClass();
Field f = c.getDeclaredField("name");
f.setAccessible(true); // 别管这个字段是不是public,一律允许访问
Object value = f.get(p); // 获取值
System.out.println(value); // "Xiao Ming"'
f.set(p, "Xiao Zhang"); // 设置值
System.out.println(p.getName()); // "Xiao Hong"
}
}
class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
setAccessible(true)可能会失败。如果JVM运行期存在SecurityManager,那么它会根据规则进行检查,有可能阻止setAccessible(true)。例如,某个SecurityManager可能不允许对java和javax开头的package的类调用setAccessible(true),这样可以保证JVM核心库的安全。
Field 类扩展方法
方法 |
描述 |
boolean isEnumConstant() | 判断是否枚举常量 |
Class<?> getType() | 获取字段类型,不包含泛型类型 |
Type getGenericType() | 获取字段类型 |
String toGenericString() | 返回描述这个字段的字符串 |
Object get(Object obj) | 获取字段值 |
boolean getBoolean(Object obj) | 获取 boolean 类型字段值 |
byte getByte(Object obj) | 获取 byte 类型字段值 |
char getChar(Object obj) | 获取 char 类型字段值 |
short getShort(Object obj) | 获取 short 类型字段值 |
int getInt(Object obj) | 获取 int类型字段值 |
long getLong(Object obj) | 获取 long类型字段值 |
float getFloat(Object obj) | 获取float类型字段值 |
double getDouble(Object obj) | 获取 double类型字段值 |
void set(Object obj, Object value) | 设置字段值 |
void setBoolean(Object obj, boolean z) | 设置boolean 类型字段值 |
void setByte(Object obj, byte b) | 设置 byte 类型字段值 |
void setChar(Object obj, char c) | 设置char 类型字段值 |
void setShort(Object obj, short s) | 设置short 类型字段值 |
void setInt(Object obj, int i) | 设置int类型字段值 |
void setLong(Object obj, long l) | 设置long类型字段值 |
void setFloat(Object obj, float f) | 设置float类型字段值 |
void setDouble(Object obj, double d) | 设置double类型字段值 |
AnnotatedType getAnnotatedType() | 返回一个AnnotatedType对象,该对象包含类型等信息 |
示例
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
public class Main {
public static void main(String[] args) throws Exception {
// 判断是否枚举常量
isEnumConstant();
// 获取字段类型,不包含泛型类型
getType();
// 获取字段类型
getGenericType();
// 返回描述这个字段的字符串
toGenericString();
// 获取/设置字段值
get$set();
// 获取/设置boolean 类型字段值
getBoolean$setBoolean();
// 获取/设置 byte 类型字段值
getByte$setByte();
// 获取/设置char 类型字段值
getChar$setChar();
// 获取/设置short 类型字段值
getShort$setShort();
// 获取/设置int类型字段值
getInt$setInt();
// 获取/设置long类型字段值
getLong$setLong();
// 获取/设置float类型字段值
getFloat$setFloat();
// 获取/设置double类型字段值
getDouble$setDouble();
//返回一个AnnotatedType对象,该对象包含类型等信息
getAnnotatedType();
}
// 判断是否枚举常量
static void isEnumConstant() {
Class clazz = Pay.class;
Field field = null;
try {
field = clazz.getDeclaredField("PAY");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
boolean isEnumConstant = field.isEnumConstant();
System.out.println("isEnumConstant = " + isEnumConstant);
}
// 获取字段类型,不包含泛型类型
static void getType() {
Class clazz = Person.class;
Field field = null;
try {
field = clazz.getDeclaredField("name");
//field = clazz.getDeclaredField("address"); // 获取不到
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
Class c = field.getType();
System.out.println("getType = " + c);
}
static void getGenericType() {
Class clazz = Person.class;
Field field = null;
try {
field = clazz.getDeclaredField("address");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
Type c = field.getGenericType();
System.out.println("getGenericType = " + c);
}
/**
* *返回描述这个{@code字段}的字符串,包括
* 其泛型类型。的访问修饰符
* 字段(如果有的话),然后是泛型字段类型,然后是
* 一个空格,后跟类的全限定名
* 声明字段,后面跟着句号,后面跟着名称
*/
static void toGenericString() {
Class clazz = Person.class;
Field field = null;
try {
field = clazz.getDeclaredField("address");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
String str = field.toGenericString();
System.out.println("toGenericString = " + str);
}
// 获取/设置 字段值
static void get$set() {
Person p = new Person();
Class clazz = Person.class;
Field field = null;
try {
field = clazz.getDeclaredField("name");
field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
//设置字段的值
field.set(p, "kevin");
// 获取字段的值
Object obj = field.get(p);
System.out.println("get$set = " + obj);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取/设置boolean 类型字段值
static void getBoolean$setBoolean() {
Person p = new Person();
Class clazz = Person.class;
Field field = null;
try {
field = clazz.getDeclaredField("deleteFlag");
field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
// 设置字段的值
field.setBoolean(p, Boolean.TRUE);
// 获取字段的值
boolean obj = field.getBoolean(p);
System.out.println("getBoolean$setBoolean = " + obj);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取/设置 byte 类型字段值
static void getByte$setByte() {
Person p = new Person();
Class clazz = Person.class;
Field field = null;
try {
field = clazz.getDeclaredField("byteField");
field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
// 设置字段的值
field.setByte(p, Byte.parseByte("3"));
// 获取字段的值
byte obj = field.getByte(p);
System.out.println("getByte$setByte = " + obj);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取/设置char 类型字段值
static void getChar$setChar() {
Person p = new Person();
Class clazz = Person.class;
Field field = null;
try {
field = clazz.getDeclaredField("charField");
field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
// 设置字段的值
field.setChar(p, '2');
// 获取字段的值
char obj = field.getChar(p);
System.out.println("getChar$setChar = " + obj);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取/设置short 类型字段值
static void getShort$setShort() {
Person p = new Person();
Class clazz = Person.class;
Field field = null;
try {
field = clazz.getDeclaredField("shortField");
field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
// 设置字段的值
field.setShort(p, Short.parseShort("2"));
// 获取字段的值
short obj = field.getShort(p);
System.out.println("getShort$setShort = " + obj);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取/设置int 类型字段值
static void getInt$setInt() {
Person p = new Person();
Class clazz = Person.class;
Field field = null;
try {
field = clazz.getDeclaredField("intField");
field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
// 设置字段的值
field.setInt(p, 2);
// 获取字段的值
int obj = field.getInt(p);
System.out.println("getInt$setInt = " + obj);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取/设置 long 类型字段值
static void getLong$setLong() {
Person p = new Person();
Class clazz = Person.class;
Field field = null;
try {
field = clazz.getDeclaredField("longField");
field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
// 设置字段值
field.setLong(p, 4L);
// 获取字段值
long obj = field.getLong(p);
System.out.println("getLong$setLong = " + obj);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取/设置 float 类型字段值
static void getFloat$setFloat() {
Person p = new Person();
Class clazz = Person.class;
Field field = null;
try {
field = clazz.getDeclaredField("floatField");
field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
// 设置字段的值
field.setFloat(p, 3.0F);
// 获取字段的值
float obj = field.getFloat(p);
System.out.println("getFloat$setFloat = " + obj);
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取/设置 double 类型字段值
static void getDouble$setDouble() {
Person p = new Person();
Class clazz = Person.class;
Field field = null;
try {
field = clazz.getDeclaredField("doubleField");
field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
// 设置字段的值
field.setDouble(p, 6.01);
// 获取字段的值
double obj = field.getDouble(p);
System.out.println("getDouble$setDouble = " + obj);
} catch (Exception e) {
e.printStackTrace();
}
}
// 返回一个AnnotatedType对象,该对象包含类型等信息
static void getAnnotatedType() {
Person p = new Person();
Class clazz = Person.class;
Field field = null;
try {
field = clazz.getDeclaredField("doubleField");
field.setAccessible(true); // 调用Field.setAccessible(true)的意思是,别管这个字段是不是public,一律允许访问
// 获取字段的值
AnnotatedType obj = field.getAnnotatedType();
System.out.println("getAnnotatedType = " + obj.getType());
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Person<T> {
private Pay pay;
private String name;
private T address;
private boolean deleteFlag;
private byte byteField;
private char charField;
private short shortField;
private int intField;
private long longField;
private float floatField;
private double doubleField;
public double getDoubleField() {
return doubleField;
}
public void setDoubleField(double doubleField) {
this.doubleField = doubleField;
}
public float getFloatField() {
return floatField;
}
public void setFloatField(float floatField) {
this.floatField = floatField;
}
public long getLongField() {
return longField;
}
public void setLongField(long longField) {
this.longField = longField;
}
public int getIntField() {
return intField;
}
public void setIntField(int intField) {
this.intField = intField;
}
public short getShortField() {
return shortField;
}
public void setShortField(short shortField) {
this.shortField = shortField;
}
public char getCharField() {
return charField;
}
public void setCharField(char charField) {
this.charField = charField;
}
public Person() {
}
public Person(String name) {
this.name = name;
}
public Person(boolean deleteFlag) {
this.deleteFlag = deleteFlag;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public byte getByteField() {
return byteField;
}
public void setByteField(byte byteField) {
this.byteField = byteField;
}
public Pay getPay() {
return pay;
}
public void setPay(Pay pay) {
this.pay = pay;
}
public T getAddress() {
return address;
}
public void setAddress(T address) {
this.address = address;
}
public boolean isDeleteFlag() {
return deleteFlag;
}
public void setDeleteFlag(boolean deleteFlag) {
this.deleteFlag = deleteFlag;
}
}
enum Pay {
PAY
}
三、调用方法
Class类提供了以下几个方法来获取Method
- Method getMethod(name, Class…):获取某个public的Method(包括父类)
- Method getDeclaredMethod(name, Class…):获取当前类的某个Method(不包括父类)
- Method[] getMethods():获取所有public的Method(包括父类)
- Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)
示例
public class Main {
public static void main(String[] args) throws Exception {
Class stdClass = Student.class;
// 获取public方法getScore,参数为String:
System.out.println(stdClass.getMethod("getScore", String.class));
// 获取继承的public方法getName,无参数:
System.out.println(stdClass.getMethod("getName"));
// 获取private方法getGrade,参数为int:
System.out.println(stdClass.getDeclaredMethod("getGrade", int.class));
}
}
class Student extends Person {
public int getScore(String type) {
return 99;
}
private int getGrade(int year) {
return 1;
}
}
class Person {
public String getName() {
return "Person";
}
}
控制台显示
public int Student.getScore(java.lang.String)
public java.lang.String Person.getName()
private int Student.getGrade(int)
一个 Method 对象包含一个方法的所有信息:
- getName() 返回方法名称
- getReturnType() 返回方法返回值类型
- getParamMeterTypers() 返回方法的参数类型,是一个 Class 数组
- getModifiers() 返回方法修饰符,它是一个 int,不同int表示不同含义
3.1、 普通方法调用
获取到一个Method对象时,就可以对它进行调用。代码为例:
String s = "Hello world";
String r = s.substring(6); // "world"
反射来调用substring方法,需要以下代码:
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Exception {
// String对象:
String s = "Hello world";
// 获取String substring(int)方法,参数为int:
Method m = String.class.getMethod("substring", int.class);
// 在s对象上调用该方法并获取结果:
String r = (String) m.invoke(s, 6);
// 打印调用结果:
System.out.println(r);
}
}
Method实例调用invoke就相当于调用该方法,invoke的第一个参数是对象实例,即在哪个实例上调用该方法,后面的可变参数要与方法参数一致,否则将报错。
3.2、 静态方法调用
获取到的Method表示一个静态方法,调用静态方法时,由于无需指定实例对象,所以invoke方法传入的第一个参数永远为null。以Integer.parseInt(String)为例:
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Exception {
// 获取Integer.parseInt(String)方法,参数为String:
Method m = Integer.class.getMethod("parseInt", String.class);
// 调用该静态方法并获取结果:
Integer n = (Integer) m.invoke(null, "12345");
// 打印调用结果:
System.out.println(n);// 12345
}
}
3.3、 非 public 方法调用
对于非public方法,虽然可以通过Class.getDeclaredMethod()获取该方法实例,但直接对其调用将得到一个IllegalAccessException。为了调用非public方法,我们通过Method.setAccessible(true)允许其调用:
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Exception {
Person p = new Person();
Method m = p.getClass().getDeclaredMethod("setName", String.class);
m.setAccessible(true);
m.invoke(p, "Bob");
System.out.println(p.name); // Bob
}
}
class Person {
String name;
private void setName(String name) {
this.name = name;
}
}
需要注意的话,setAccessible(true)可能会失败。如果JVM运行期存在SecurityManager,那么它会根据规则进行检查,有可能阻止setAccessible(true)。例如,某个SecurityManager可能不允许对java和javax开头的package的类调用setAccessible(true),这样可以保证JVM核心库的安全。
3.4、 多态方法调用
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Exception {
// 获取Person的hello方法:
Method h = Person.class.getMethod("hello");
// 对Student实例调用hello方法:
h.invoke(new Student());
}
}
class Person {
public void hello() {
System.out.println("Person:hello");
}
}
class Student extends Person {
public void hello() {
System.out.println("Student:hello");
}
}
控制台显示
Student:hello
使用反射调用方法时,仍然遵循多态原则:即总是调用实际类型的覆写方法(如果存在)。上述的反射代码:
Method m = Person.class.getMethod("hello");
m.invoke(new Student());
相当于:
Person p = new Student();
p.hello();
Method扩展方法
方法 |
描述 |
Class<?> getReturnType() | 获取方法返回类型 |
Type getGenericReturnType() | 获取方法返回类型,返回类型是参数化类型 |
Object invoke(Object obj, Object… args) | 调用该方法并获取结果 |
boolean isBridge() | 判断是否桥接方法 |
boolean isDefault() | 判断是否isDefault方法 |
Object getDefaultValue() | 获取默认值 |
示例
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Comparator;
public class Main {
public static void main(String[] args) throws Exception {
// 获取方法返回类型
getReturnType();
// 获取方法返回类型,返回类型是参数化类型
getGenericReturnType();
//调用该方法并获取结果
invoke();
// 判断是否桥接方法
isBridge();
// 判断是否isDefault方法
isDefault();
// 获取默认值
getDefaultValue();
}
// 获取方法返回类型
static void getReturnType() {
Person p = new Person();
Method m = null;
try {
m = p.getClass().getDeclaredMethod("getName");
m.setAccessible(true);
Class clazz = m.getReturnType();
System.out.println("getReturnType= " + clazz);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
// 获取方法返回类型,返回类型是参数化类型
static void getGenericReturnType() {
Person p = new Person();
Method m = null;
try {
m = p.getClass().getDeclaredMethod("say");
m.setAccessible(true);
Type clazz = m.getGenericReturnType();
System.out.println("getGenericReturnType= " + clazz);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
//调用该方法并获取结果:
static void invoke() {
Student p = new Student();
Method m = null;
try {
m = p.getClass().getDeclaredMethod("setName", String.class);
m.setAccessible(true);
m.invoke(p, "Kevin");
System.out.println("invoke= " + p.name);
} catch (Exception e) {
e.printStackTrace();
}
}
// 判断是桥接方法
static void isBridge() {
Class<B> classB = B.class;
Method[] methods = classB.getDeclaredMethods();
System.out.println("方法总数量:" + methods.length);
for (Method method : methods) {
System.out.println(method.getReturnType().getSimpleName() + " "
+ method.getName() +
"(" + method.getParameters()[0].getType().getSimpleName() + ")"
+ " is " + (method.isBridge() ? "bridge" : "common") + " method"
);
}
}
// 判断是否isDefault方法
static void isDefault() {
Class c = Comparator.class;
Method[] methods = c.getMethods();
for (Method method : methods) {
// check whether method is Default Method or not
if (method.isDefault()) {
// print Method name
System.out.println("isDefault = " + method.getName() + " " + method.isDefault());
}
}
}
// 获取默认值
static void getDefaultValue() {
try {
Method method = AnnotationDemo.class.getDeclaredMethod("fauvMovie");
System.out.println("getDefaultValue =" + method.getDefaultValue());
} catch (Exception e) {
}
}
}
@interface AnnotationDemo {
public String fauvMovie() default "Inception";
public double fauvMovieRating() default 9.6;
public int fauvMovieReleaseYear();
}
class Person<T> {
String name;
private void setName(String name) {
this.name = name;
}
public T say() {
return null;
}
public String getName() {
return name;
}
}
class Student {
String name;
private void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// 声明一个泛型接口
interface A<T> {
void test(T t);
}
//泛型本身是语言级别的,经过编译后,泛型就会被擦除,所以接口 A 在编译后,test 方法的入参会被转换为 Object
//编译器编译
//public interface A {
// void test(Object t);
//}
// 使用 String 类型实现一个具体的实现类
class B implements A<String> {
public void test(String s) {
System.out.println(s);
}
}
//实现类 B 中的实现方法是 void test(String s),其实根本就没有实现 void test(Object t) 方法。但是这个代码是正确的,可以正常运行,因为 JVM 在编译过程中对我们的实现类做了一点手脚
//编译器编译
//public class B implements A {
// public void test(String s) {
// System.out.println(s);
// }
// public void test(Object s) {
// this.test((String) s);
// }
//}
四、调用构造方法
通过创建对象实例:
Person p = new Person();
调用Class提供的newInstance()方法
Person p = Person.class.newInstance();
调用Class.newInstance()的局限是,它只能调用该类的public无参数构造方法。如果构造方法带有参数,或者不是public,就无法直接通过Class.newInstance()来调用。
为了调用任意的构造方法,Java的反射API提供了Constructor对象,它包含一个构造方法的所有信息,可以创建一个实例。Constructor对象和Method非常类似,不同之处仅在于它是一个构造方法,并且,调用结果总是返回实例:
import java.lang.reflect.Constructor;
public class Main {
public static void main(String[] args) throws Exception {
// 获取构造方法Integer(int):
Constructor cons1 = Integer.class.getConstructor(int.class);
// 调用构造方法:
Integer n1 = (Integer) cons1.newInstance(123);
System.out.println(n1);
// 获取构造方法Integer(String)
Constructor cons2 = Integer.class.getConstructor(String.class);
Integer n2 = (Integer) cons2.newInstance("456");
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)可能会失败。