Class类的使用 java.lang.Class
1.1在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息。
1.2获取Class实例方式
方法1
利用对象调用getClass()方法获取该对象的Class实例;
方法2
使用Class类的静态方法forName(), 用类的名字获取一个Class实例(staticClass forName(String className) Returns the Classobject associated with the class or interface with the given stringname. );
方法3
运用.class的方式来获取Class实例,对于基本数据类型的封装类,还可以采用.TYPE来获取相对应的基本数据类型的Class实例
在newInstance()调用类中缺省的构造方法 ObjectnewInstance()(可在不知该类的名字的时候,创建这个类的实例) Creates a new instance of the class represented by this Classobject.
在运行期间,如果我们要产生某个类的对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象 [1]
打印类的类信息
/**
* 打印类的信息,包含类的成员函、数成员变量
*/
public static void printClassMessage(Object obj) {
// 要获取类的信息 首先要获取类的类类型c
Class c = obj.getClass(); // 传递的是哪个子类的对象 c就是该子类的类类型
// 获取类的名字
System. out .println("类的名称是:" + c.getName());
/*
* Method类,方法对象 一个成员方法就是一个Method对象
* getMethod方法()获取所有public的函数,包括父类继承而来的方法。
* getDeclaredMethods()获取的是所有该类自己声明的方法,不问访问权限
*/
Method[] ms = c.getDeclaredMethods();
for (Method method : ms) {
Class returnType = method.getReturnType();// 得到方法的返回值类型的类类型
System. out .println(returnType.getName() + " ");
System. out .print(method.getName());// 得到方法名称
StringBuilder paramStr = new StringBuilder();
Class[] paramTypes = method.getParameterTypes();// 获取参数类型-->得到的是参数列表的类型的类类型
if (paramTypes != null && paramTypes. length > 0) {
paramStr.append( "(" );
for (Class type : paramTypes) {
paramStr.append(type.getName() + "," );
}
paramStr.deleteCharAt(paramStr.length() - 1);
paramStr.append( ")" );
} else {
paramStr.append( "()" );
}
System. out .println(paramStr.toString());
/*
* 成员变量也是对象java.lang.reflect.Field Field类封装了关于成员变量的操作
* getFields获取所有的public的成员变量的信息 getDeclaredFields()获取该类自己声明的成员变量的信息
*/
Field[] fs = c.getDeclaredFields();
if (fs != null && fs. length > 0) {
for (Field field : fs) {
// 得到成员变量的类型的类类型
Class fType = field.getType();
System. out .println(fType.getName() + ":" + field.getName());
}
}
/*
* 构造函数也是对象 java.lang.Constructor中封装了构造函数的信息
* c.getDeclaredConstructors() 得到所有自己声明的构造方法
*/
Constructor[] cs = c.getDeclaredConstructors();
System. out .println(cs.length );
if (cs != null && cs. length > 0) {
StringBuilder csStr = new StringBuilder();
for (Constructor constructor : cs) {
csStr.append(constructor.getName());
csStr.append( "(" );
Class[] ctypes = constructor.getParameterTypes();
if (ctypes != null && ctypes.length > 0) {
for (Class type : ctypes) {
csStr.append(type.getName() + "," );
}
csStr.deleteCharAt(csStr.length() - 1);
}
csStr.append( ")" );
}
System. out .println(csStr.toString());
}
}
}
1.3方法的反射
1)如何获取某个方法?
方法名和方法的参数列表才能唯一的决定某个方法
2)方法反射的操作
method.invoke(对象,参数列表)
实例:
public
static
void
main(String[] args) {
//如何获取指定print方法,1.要获取一个方法就是获取类的信息,获取类的信息首先要获取类的类对象
Class c = A.
class
;
/*
*2.获取方法 名称和参数列表来决定唯一的方法
*class...或者 int...等等 代表的意思是需要1个或多个参数,可以传递new Class[]{X,X,X}或者x,x,x这两种类型的参数
*getMethod获取的是public的方法
*getDeclaredMethod获取的是自己声明的方法
*/
try
{
Method method = c.getDeclaredMethod(
"print"
,
int
.
class
,
int
.
class
) ;
method.invoke(c.newInstance(), 1,1);
//方法的反射操作,通过方法来操作类去执行。
Method method1 = c.getDeclaredMethod(
"print"
,
new
Class[]{String.
class
,String.
class
}
)
;
method1.invoke(c.newInstance(),
"hello"
,
"World"
);
//方法的反射操作,通过方法来操作类去执行。
}
catch
(Exception e) {
e.printStackTrace();
}
}
class
A {
public
void
print(
int
a,
int
b){
System.
out
.println(a+b);
}
public
void
print(String a,String b){
System.
out
.println(a+b);
}
}
1.4通过反射了解集合泛型的本质
List a =
new
ArrayList ();
List b =
new
ArrayList();
Class ca = a.getClass();
Class cb = b.getClass();
//看看list集合的类对象是否相同
System.
out
.println(ca==cb);
/*
*返回结果为true,虽然2个集合的泛型不同,但是类的类对象相同
*也说明Java中集合的泛型,是防止错误输入的只在编译阶段有效,绕过编译就无效了。
*验证:方法的反射来操作,绕过编译
*/
try
{
Method m = cb.getMethod(
"add"
, Object.
class
);
m.invoke(b, 100);
System.
out
.println(b.size());
System.
out
.println(b);
for
(
int
i = 0; i < b.size(); i++) {
Object obj = b.get(i);
System.
out
.println(obj);
}
}
catch
(Exception e) {
e.printStackTrace();
}