什么是反射
以往我们使用类和对象的顺序都是,先创建好类,然后再通过类创建对象。和这不同的是,反射的工作主要是先拿到对象然后根据对象倒推类的组成。
也许你会问,虽然我拿到了对象,但是我怎么知道类里有啥呢?发射的核心处理在于每个类都继承了Object类
这种操作就很像盗版的操作:原创是先有的构想,然后设计图纸,然后创建出模型,再生产出产品。而盗版却是已经拿到了产品,但是想利用这个产品倒退出模型然后再创作出新的产品。
哇,反射肯定比正常使用麻烦吧?不一定哦
如何取得对象的Class对象
1.实例化对象.getClass()
任何类得对象都可以直接通过调用Object类提供的getClass()取得该类的Class对象。
2.类名.class
可以直接根据某个具体类名称类取得它的Class类对象
3.Class.forName("类的全路径名称")
调用Class类的静态方法Class.forName(String className)通过传入类的全路径名称类来获取Class对象
为什么可以通过.getClass(),或者.class取得呢?
因为每一个我们创建的类都继承类Object类,而Object中提供了获取类对象的本地方法,也就是说一个类里包含的东西,不只是我们看到的那么几个哦~
任何一个类的Class对象都是由JVM皆在类后就产生了,而且这个类的Class对象在JVM中全局唯一,用户只能通过调用我们上述提供的三种方法来获取该对象,是不能够自己创造的哦
通过Class对象反射产生实例化对象
1.Class类中提供public T newInstance()
方法来调用类中公有public属性的无参数的构造方法来实例化对象。
Class<?> cls = emp.getClass();
Object obj = cls.newInstancle();
2.Constructor类提供类public T newInstance(Object...initargs)
方法来调用类中有参数的构造方法来实例化对象。
//调用emp类的带有String类型参数的构造方法
Class<?> cls = emp.getClass();
Constructor<?> constructor =cls.getConstructor(String.class);
Object obj = constructor.newInstance("name");
通过这个方法只要拿到类的全路径和名称,就可以实例化一个对象了。
通过反射取得父类、以及父接口信息-Class类提供
1.取得父类名称
public Package getPackage()
2.取得父类的Class对象 <? super T>设置了下限
public native Class<? superT > getSuperclass()
3.取得实现了的父接口 --不一定是一个哦,实现接口没有单继承局限哦
public Class<?>[] getInterfaces()
通过反射调用类中构造方法-Constructor类提供
1.取得类中指定参数类型的public权限的构造方法
public Constructor<T> getConstructor(Class<?>... parameterTypes)
2.可以取得类中指定参数的构造方法,会在所有构造中找,包括私有权限的
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)throws NoSuchMethodException, SecurityException
3.取得类中所有public权限的构造方法
public Constructor<?>[] getConstructors() throws SecurityException
4.取得类中所有构造方法包括私有,默认,继承,共有权限的
public Constructor<?>[] getDeclaredConstructors() throws SecurityException
5.通过对应构造实例化对象
public T newInstance(Object ... initargs)
6.提供动态破坏封装,想要破坏封装参数传true就删除了指定构造方法的私有权限,但是只能通过本类提供的方法来调用。
public void setAccessible(boolean flag) throws SecurityException
通过反射调用类中普通方法-Method类提供
1.取得类中制定名称的公有普通方法
public Method getMethod(String name, Class<?>... parameterTypes)
2.取得类中指定名称的不限权限的普通方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
3.取得本类以及父类中所有public方法
public Method[] getMethods() throws SecurityException
4.取得本类中全部普通方法,包括私有方法
public Method[] getDeclaredMethods() throws SecurityException
5.⭐Methrod类提供调用类的普通方法的方法,不然我通过上述操作拿到了Method类型的方法,但是不能使用,因为没有啊,因为普通方法的调用和对象有关,所以需要我们第一个参数传入想要调用这个类的对象,而可变参数则是这个普通方法实际需要传入的参数。
public Object invoke(Object obj, Object... args)
举个例子:
import java.lang.reflect.Method;
class Person{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return getClass()+"\t:"+name;
}
}
public class Test{
public static void main(String[] args)throws Exception{
Class<?> cls = Person.class;
Person person = (Person) cls.newInstance();
Method setMethod = cls.getMethod("setName", String.class);
setMethod.invoke(person,"hahaha");
System.out.println(person);
}
}
6.提供动态破坏封装,想要破坏封装参数传true就删除了指定普通方法的私有权限,但是只能通过本类提供的方法调用。
public void setAccessible(boolean flag) throws SecurityException
通过反射调用类中属性-Field类提供
1.取得类中指定名称的public权限的属性
public Field getField(String name)
2.取得类中指定属性在所有权限中找
public Field getDeclaredField(String name)
3.取得类中全部属性取得类中全部公有属性
public Field[] getFields() throws SecurityException
4.取得本类中全部普通属性,包含私有属性
public Field[] getDeclaredFields()
5.设置取得属性
//设置属性:
public void set(Object obj, Object value)
//取得属性:
public Object get(Object obj)
6.取得属性类型
public Class<?> getType()
7.提供动态破坏封装,想要破坏封装参数传true就删除了指定属性的私有权限,但是只能通过本类提供的方法修改,拿到对应值。
public void setAccessible(boolean flag) throws SecurityException