Class
java 为每一个对象实例都维护了一个Class类,虚拟机使用这个对象来跟踪对象所属的类
Tips:
RTTI(Run-Time Type Identification)运行时类型识别。这种技术实现了多态的概念。而这种技术在Java中是通过Class 来实现的。
如何获得class呢?
- getClass();
Object(所有类的父类)有一个getClass可以获得Class对象 - Class.forName();
静态方法可以传入一个字符串来初始化class类,如java.util.Date - T.class T是任意类型如
Class c1=String.class;
Class c2=int.class;
Class c3=Double [].class;
可以使用Class来判断对象所属的类
if(new String().getClass()==String.class){}
//或者
if(new String() instanceof String)
Class类中的一些方法
我们可以使用class.newinstance()方法来实例化一个对象。
try {
String s=(String) Class.forName("java.lang.String").newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
TIps:
newinstance只能调用默认的构造函数,如果没有默认函数会抛出异常
反射
反射是什么?通过反射我们可以知道一个类中有什么从而动态初始化类。例如下面的例子可以打印一个类中的成员。代码来自《java 核心技术》
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.Date;
import java.util.Scanner;
public class Test {
String s;
public static void main(String [] args){
Scanner in=new Scanner(System.in);
System.out.println("Pease input a class name for whcih you wanna looking ");
String classname=in.nextLine();
try {
Class c= Class.forName(classname);
String modifier=Modifier.toString(c.getModifiers());
if(modifier.isEmpty()!=true) System.out.print(modifier+" ");
System.out.println(c);
Class superc=c.getSuperclass();
if(superc!=null&&superc!=Object.class)System.out.print("extends"+superc.getName());
System.out.print("{\n");
printConstructor(c);
System.out.println();
printmethods(c);
System.out.println();
printFileds(c);
System.out.print("\n}");
} catch (SecurityException | ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void printFileds(Class c) {
// TODO Auto-generated method stub
Field[] fs=c.getFields();
for(Field f:fs){
System.out.print(" ");
String modifier=Modifier.toString(f.getModifiers());
System.out.print(modifier+" ");
System.out.println(f.getName());
}
}
private static void printmethods(Class c) {
// TODO Auto-generated method stub
Method [] ms=c.getMethods();
for(Method m: ms){
String name=m.getName();
System.out.print(" ");
String modifier=Modifier.toString(m.getModifiers());
System.out.print(modifier+" ");
System.out.print(name+"(");
Class[] cs=m.getParameterTypes();
for( int j=0;j<cs.length;j++){
if(j>0)System.out.print(",");
System.out.print(cs[j].getName());
}
System.out.println(");");
}
}
private static void printConstructor(Class c) {
// TODO Auto-generated method stub
Constructor[] constructors=c.getConstructors();
for(Constructor cons: constructors){
String name=cons.getName();
System.out.print(" ");
String modifier=Modifier.toString(cons.getModifiers());
System.out.print(modifier+" ");
System.out.print(name+"(");
Class[] cs=cons.getParameterTypes();
for( int j=0;j<cs.length;j++){
if(j>0)System.out.print(",");
System.out.print(cs[j].getName());
}
System.out.println(");");
}
}
}
从上面代码案例我们可以知道,想要得到一个对象的全部信息,首先要得到它的Class对象。之后就可以从Class对象中提取它的Filed,Method,Constructor对象。我们就可以用如下方法来工作了。
getxxx():返回所有共有方法或属性
getdeclaredxxx():返回所有属性和方法
getdeclaringClass()
逆向找到方法/属性所属的Class
getExceptionTypes()
返回方法抛出的异常
getReturnType
返回方法返回的类型
getmodifier()
放回访问修饰符
Modifier类中有很多静态方法isxxx()来判断有没有某一种访问修饰符。也可以用toString()直接输出访问修饰符。
注意:
getDeclaredxxx()方法可一返回私有域。但是因为java 的安全机制我们是不能查看其中的值的。
User u=new User();
Filed f=u.class.getDeclaredFiled("name")
Object o=f.get(U);
//请注意get方法的使用
因为name是User的私有域, 所以我们是不可以访问的。会爆出一个illegalAccessException。但是我们可以修改默认的安全机制使其可以读取私有域中的值。只需要调用Filed,Method,Constructor对象setAccessible(true).