反射
一个类对应一个class文件,class 文件存储的是这个类的信息,反射就是通过得到 class 对象后再得到类的信息。
获得class 对象的三种方法
1.对象.getclass()
2.类名.class
3.通过class对象的forName()静态方法获取。
public static void main(String[] args) throws ClassNotFoundException {
/**
* 第一种方法得到 class 对象
* 对象.getclass()方法。
*/
Students s = new Students();
Class c1 = s.getClass();
/**
* 第二种方法得到 class 对象
* 直接通过类名.class 方式
* 这说明任何一个对象都有一个隐含的静态成员变量 class
* 这种方法比较安全可靠。
*/
Class c2 = Students.class;
/**
* 第三种方法得到 class 对象
* 通过 class 对象的 forName()静态方法来获取
* 可能要抛出 ClassNotFoundException 异常。
*/
Class c3 = Class.forName("com.Students");
System.out.println(c1.equals(c2));//true
System.out.println(c1.equals(c3));//true
System.out.println(c3.equals(c2));//true
}
通过最后的比较,我们可以看出这三个class对象是同一个。
查阅 API 可以看到 Class 有很多方法:
getName():获得类的完整名字。
getFields():获得类的public类型的属性。
getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
getMethods():获得类的public类型的方法。
getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,
parameterTypes 参数指定方法的参数类型。
getConstructors():获得类的public类型的构造方法。
getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
我们看看几个常用的方法
获取类的完整路径名
public static void main(String[] args) throws ClassNotFoundException {
/**
* getName(); 获得类的完整路径。
*/
String classname = c1.getName();
System.out.println(classname);
}
运行结果:com.Students
获得类的所有成员
public static void main(String[] args) throws ClassNotFoundException {
* 得到类的所有数据成员、包括私有成员
* Field[]
*/
Field[] fileds2 = c1.getDeclaredFields();
for(Field field : fileds2){
System.out.println(field.getName());
}
}
运行结果:
name
age
获得类的所有方法
public static void main(String[] args) throws ClassNotFoundException {
/**
* 获得类的所有成员方法
* Method[]
*/
Method[] methonds = c1.getDeclaredMethods();
for(Method methond : methonds){
System.out.println(methond.getName());
}
}
运行结果:
fun1
fun2
获得类的 构造函数
public static void main(String[] args) throws ClassNotFoundException {
/**
* 得到 public 类型的构造函数
* Constructor
*/
Constructor[] conArray = c1.getConstructors();
for(Constructor c : conArray){
System.out.println(c);
}
}
运行结果:
public com.Students()
反射的不安全之处
public static void main(String[] args){
/** * 不安全之处 * */ Field f2 = c1.getDeclaredField("name");//抛出异常System.out.println(f2);f2.setAccessible(true);//变为false后下面就不可以改变name的值了//设置可见性//不安全之处,通过获得一个这个类的对象Object p2 = c1.newInstance();//抛出异常f2.set(p2,"wjm");System.out.println(f2.get(p2));}
运行结果:
wjm