构造函数用于创建一个作为类的实例的对象。通常,在方法被调用或字段被访问之前,它执行初始化类所需的操作。构造函数是不被继承的。
在处理构造函数时使用的关键类是Class和java.lang.reflect.Constructor。本帖的源代码可在GitHub上找到。
下面的类图显示了java.lang.reflect.Constructor提供的反射API的列表。
Java 构造函数的反射
构造函数声明包括名称、修改器、参数和可抛出的异常列表。java.lang.reflect.Constructor类提供了一种获取这些信息的方法。
ConstructorSift 示例说明了如何在一个类的声明构造函数中搜索一个有指定类型参数的构造函数。
package com.javaguides.reflection.constructors;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import static java.lang.System.out;
public class ConstructorSift {
public static void main(String... args) {
try {
Class<?> cArg = Class.forName("java.util.Locale");
Class<?> c = Class.forName("java.util.Formatter");
Constructor[] allConstructors = c.getDeclaredConstructors();
for (Constructor ctor : allConstructors) {
Class<?>[] pType = ctor.getParameterTypes();
for (int i = 0; i < pType.length; i++) {
if (pType[i].equals(cArg)) {
out.format("%s%n", ctor.toGenericString());
Type[] gpType = ctor.getGenericParameterTypes();
for (int j = 0; j < gpType.length; j++) {
char ch = (pType[j].equals(cArg) ? '/*' : ' ');
out.format("%7c%s[%d]: %s%n", ch,
"GenericParameterType", j, gpType[j]);
}
break;
}
}
}
// production code should handle this exception more gracefully
} catch (ClassNotFoundException x) {
x.printStackTrace();
}
}
}
输出。
public java.util.Formatter(java.lang.String,java.lang.String,java.util.Locale)
throws java.io.FileNotFoundException,java.io.UnsupportedEncodingException
GenericParameterType[0]: class java.lang.String
GenericParameterType[1]: class java.lang.String
*GenericParameterType[2]: class java.util.Locale
public java.util.Formatter(java.io.File,java.lang.String,java.util.Locale)
throws java.io.FileNotFoundException,java.io.UnsupportedEncodingException
GenericParameterType[0]: class java.io.File
GenericParameterType[1]: class java.lang.String
*GenericParameterType[2]: class java.util.Locale
private java.util.Formatter(java.nio.charset.Charset,java.util.Locale,java.io.File)
throws java.io.FileNotFoundException
GenericParameterType[0]: class java.nio.charset.Charset
*GenericParameterType[1]: class java.util.Locale
GenericParameterType[2]: class java.io.File
private java.util.Formatter(java.util.Locale,java.lang.Appendable)
*GenericParameterType[0]: class java.util.Locale
GenericParameterType[1]: interface java.lang.Appendable
public java.util.Formatter(java.io.OutputStream,java.lang.String,java.util.Locale)
throws java.io.UnsupportedEncodingException
GenericParameterType[0]: class java.io.OutputStream
GenericParameterType[1]: class java.lang.String
*GenericParameterType[2]: class java.util.Locale
public java.util.Formatter(java.lang.Appendable,java.util.Locale)
GenericParameterType[0]: interface java.lang.Appendable
*GenericParameterType[1]: class java.util.Locale
public java.util.Formatter(java.util.Locale)
*GenericParameterType[0]: class java.util.Locale
由于构造函数在语言中的作用,有意义的修饰符比方法少。
package com.javaguides.reflection.constructors;
import static java.lang.System.out;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class ConstructorAccess {
public static void main(String... args) {
try {
Class<?> c = Class.forName("java.io.File");
Constructor[] allConstructors = c.getDeclaredConstructors();
for (Constructor ctor : allConstructors) {
int searchMod = modifierFromString("private");
int mods = accessModifiers(ctor.getModifiers());
if (searchMod == mods) {
out.format("%s%n", ctor.toGenericString());
out.format(" [ synthetic=%-5b var_args=%-5b ]%n", ctor.isSynthetic(), ctor.isVarArgs());
}
}
// production code should handle this exception more gracefully
} catch (ClassNotFoundException x) {
x.printStackTrace();
}
}
private static int accessModifiers(int m) {
return m & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED);
}
private static int modifierFromString(String s) {
if ("public".equals(s))
return Modifier.PUBLIC;
else if ("protected".equals(s))
return Modifier.PROTECTED;
else if ("private".equals(s))
return Modifier.PRIVATE;
else if ("package-private".equals(s))
return 0;
else
return -1;
}
}
输出:
private java.io.File(java.lang.String,java.io.File)
[ synthetic=false var_args=false ]
private java.io.File(java.lang.String,int)
[ synthetic=false var_args=false ]
。
有两种创建类实例的反射方法:java.lang.reflect.Constructor.newInstance() 和 Class.newInstance()。
package com.javaguides.reflection.constructors;
import java.io.Console;
import java.nio.charset.Charset;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import static java.lang.System.out;
public class ConsoleCharset {
public static void main(String... args) {
Constructor[] ctors = Console.class.getDeclaredConstructors();
Constructor ctor = null;
for (int i = 0; i < ctors.length; i++) {
ctor = ctors[i];
if (ctor.getGenericParameterTypes().length == 0)
break;
}
try {
ctor.setAccessible(true);
Console c = (Console) ctor.newInstance();
Field f = c.getClass().getDeclaredField("cs");
f.setAccessible(true);
out.format("Console charset : %s%n", f.get(c));
out.format("Charset.defaultCharset(): %s%n", Charset.defaultCharset());
// production code should handle these exceptions more gracefully
} catch (InstantiationException x) {
x.printStackTrace();
} catch (InvocationTargetException x) {
x.printStackTrace();
} catch (IllegalAccessException x) {
x.printStackTrace();
} catch (NoSuchFieldException x) {
x.printStackTrace();
}
}
}
输出:
Console charset : windows-1252
Charset.defaultCharset(): windows-1252
让我们再来学习几个例子,首先创建Customer.java类并在Customerclass上应用反射构造器API。
###Customer.java
package com.javaguides.reflection.constructors;
public class Customer {
private int id;
private String firstName;
private String lastName;
public Customer(int id, String firstName, String lastName) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
在一个对象的类表示中使用getConstructor()_方法来获取特定的公共构造函数。
Class<?> clazz = Class.forName("com.javaguides.reflection.constructors.Customer");
Constructor<?> constructor = clazz.getConstructor(int.class, String.class, String.class);
// getting constructor parameters
System.out.println(Arrays.toString(constructor.getParameterTypes()));
Constructor<?> hashMapConstructor = Class.forName("java.util.HashMap").getConstructor(null);
System.out.println(Arrays.toString(hashMapConstructor.getParameterTypes()));
输出:
[int, class java.lang.String, class java.lang.String]
[]
让我们使用构造函数反射API来获取客户构造函数信息。
Class<?> clazz = Class.forName("com.javaguides.reflection.constructors.Customer");
Constructor[] constructors = clazz.getConstructors();
for (Constructor<?> constructor : constructors) {
// get constructor name
System.out.println(constructor.getName());
// get constructor parameters
System.out.println(Arrays.toString(constructor.getParameterTypes()));
// Get parameter count
System.out.println(constructor.getParameterCount());
System.out.println(constructor.getDeclaringClass().getCanonicalName());
}
输出:
com.javaguides.reflection.constructors.Customer
[int, class java.lang.String, class java.lang.String]
3
com.javaguides.reflection.constructors.Customer
https://docs.oracle.com/javase/tutorial/reflect/class/index.html
https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/package-summary.html
https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Constructor.html
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://www.javaguides.net/2018/07/java-reflection-for-constructors.html
内容来源于网络,如有侵权,请联系作者删除!