反射概述
- java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。
- 对于任意一个对象,都能够调用它的任意一个方法和属性。
- 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
- 要想解剖一个类,必须先要获取到该类的字节码文件对象
- 而解剖使用的就是Class类中的方法,所以要先获取到每一个字节码文件对应的Class类型的对象
三种方式调用Class类(反射源头)
- Object类的getClass()方法,判断两个对象是否是同一个字节码文件
//判断是否是同一个字节码对象
//Person p = new Person();
Class clazz = p.getClass();
面试题:请解释Object类中的所有方法以及每一个方法使用上的注意事项:
- 对象克隆:public Object clone() throws CloneNotSupportdException;
克隆对象所在的类一定要实现java.lang.Cloneable接口,而且子类只需要继续Object类的Clone()方法就可以成功实现克隆操作 - 对象输出:public String toString()
直接输出对象时会默认调用toString()方法 - 对象比较:public boolean equals(Object obj)
当保存Set集合时,会依靠hashCode()和equals()判断是否为重复对象 - 取得对象的hash码:public int hashCode()
可以理解为每一个类对象的唯一编码,比较时会先判断编码是否相同,而后再调用equals()比较内容; - 取得Class类对象:public Class> getClass();
通过一个已经实例化好的对象进行对象的反射操作 - 线程等待:public void wait() InterceptorException
执行到此代码时线程要等待执行,一直到执行notify(),notifyAll() - 唤醒第一个等待线程:public void notify()
- 唤醒全部等待线程:public void notifyAll();
- 垃圾回收前释放:public void finalize() htrows Throwable;
当使用gc回收无用垃圾空间时默认调用
- 静态属性Class,锁对象(Hiberate)
//当作静态方法的锁对象
//Person.class
Class clazz = Person.class
- Class类中静态方法forName(),读取配置文件
//读取配置文件
//Person.java
Class clazz = class.forName("类全限定名");
利用反射实例化对象
package cn.jishuz.demo;
class Student{
public Student() {
System.out.println("Student类的构造方法");
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "Student类的toString()方法";
}
}
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class> cls = Class.forName("cn.jishuz.demo.Student");
// 相当于关键字new实例化对象,等价:Object obj = new Object();
Object obj = cls.newInstance();
System.out.println(obj);
}
}
++必须要求类中存在无参构造方法,否则报错: java.lang.InstantiationException++
操作构造方法
可以解决上面实例化必须要无参构造的现象
在Class类里面定义了可以取得一个类之中构造方法的操作:
- 取得类之中的全部构造(预先不知道构造的参数类型时可以先打印它的所有构造):public Constructor>[] getConstructors()
- 取得类之中指定参数的构造:public Constructor
getConstruct(Class>... parameterTypes)
package cn.jishuz.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
class Student{
private String name;
private Integer age;
public Student(String name,Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "姓名:"+ this.name+",年龄:"+this.age;
}
}
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class> cls = Class.forName("cn.jishuz.demo.Student");
Constructor> cons = cls.getConstructor(String.class,Integer.class);
// 相当于关键字new实例化对象,等价:Object obj = new Object();
// Object obj = cls.newInstance();
Object obj = cons.newInstance("TOM",20);
System.out.println(obj);
}
}
调用类中方法
取得了类的实例化对象后就可以开始调用类中的方法。
两种类型:
- 取得父类继承而来的方法:
1.取得全部方法:
public Method[] getMethods()
throws SecurityException
2.获取指定方法:
public Method getMethod(String name,Class>... parameterTypes)
throws NoSuchMethodException, SecurityException
- 取得本类定义的方法:
1.取得全部方法:
public Method[] getDeclaredMethods()
throws SecurityException
2.获取指定方法
public Method getDeclaredMethod(String name, Class>... parameterTypes)
throws NoSuchMethodException, SecurityException
范例:
package cn.jishuz.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
interface Message{
public void get();
}
class Student implements Message{
@Override
public void get() {}
public void fun(){}
public void print(){}
}
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class> cls = Class.forName("cn.jishuz.demo.Student");
Method met[] = cls.getMethods();
for(int x= 0;x
其它
取得方法修饰符:public int getModifiers();
- 修饰符int转换为String:
public static String toString(int mod);
取得方法的返回参数类型:public Class> getReturnType();
- getSimpleName()得到简称
取得方法的参数:public Class>[] getParameterTypes();
取得所有抛出的异常:public Class>[] getExceptionTypes()
++反射调用类中的方法++:public Object invoke(Object obj,Object... args)
调用类中的属性(尽量不要去使用)
支持的方法有两类:
- 取得所有继承而来的属性:
- 取得全部属性:public Field[] getFields()
- 取得指定属性:public Field getField(String name)
- 取得本类定义的属性:
- 取得全部属性:public Field[] getDeclaredFields()
- 取得指定属性:public Field getDeclaredField(String name)
package cn.jishuz.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
interface Message{
public static final String INFO = "hello world.";
}
class Person{
private String name;
private Integer age;
}
class Student extends Person implements Message{
private String school;
private Double price;
}
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Class> cls = Class.forName("cn.jishuz.demo.Student");
{//取得继承而来的全部属性
Field fields[] = cls.getFields();
for(int x= 0;x
在Field类里面还定义有进行属性调用的方法:
- 设置属性内容:public void set(Object obj,Object value)
- 取得属性内容:public Object get(Object obj)
在Constrcutor、Method、Field三个类上有一个共同的父类AccessibleObject,在这个类里面定义了可以取消封装的方法:public void etAccessible(boolean flag);设置成true即可取消封装。
觉得还行可以点个星星哦