反射是对象的反射处理操作。
先来看看“正”操作。
在默认情况下,必须要先导入一个包,而后才能产生类的实例化对象。
如下就是一个正操作。
import java.util.Date;//导入的包
public class Test{
public static void main(String[] args){
Date date = new Date();//产生Date类的实例化对象
//...使用产生的date引用调用类中的方法,属性
}
}
而反操作就是根据对象来取得对象的源,反射的核心处理就在于Object类中的一个方法:
取得类的Class对象
public final native Class> getClass();
//返回类型为泛型表示可以是任意的Class对象,Class描述的就是一个类。
例如:
import java.util.Date;//导入的包
public class Test{
public static void main(String[] args){
Date date = new Date();//产生Date类的实例化对象
//反射通过对象获取到对象的来源
System.out.println(date.getClass());
}
}
输出:
class java.util.Date
通过date.getClass() (对象.getClass())可以得到Class类的对象。
反射的第一步就是拿到Class对象,而拿到Class类对象有三种实例化模式
首先,我想先说一下什么是Class类,为什么我们可以通过对象反射得到Class对象,得到Class对象我们能干什么。
什么是Class类
Class类是反射的源头,也是对整个类的描述,具有相应类的一切信息。
在Java中一切皆对象,而对象都是由类产生的,也就是Java中有各种各样的类,而这些类都是同一种类—>Class类。
举个例子来说:
人,有各种各样的人 而这些人属于一类,那就是人类
同理,java类,有各种各样的类, 而这些类属于同一类,那就是Class类。
区分: class是关键字,定义类时使用,Class是类名
一个类被类加载器加载到内存中占用一片存储空间,这个空间中的内容称为类的字节码,不同的类的字节码是不同的,所以他们在内存中的内容是不同的,而各个字节码可以用不同的Class类对象来表示。
比如:Date date = new Date();
当使用到Date类时,类加载器会将Date类加载到内存中,以字节码的形式存在。而Date.getClass();就是得到属于Date的那份字节码,返回Date类。每个类中包含的属性是类的名字,类的访问属性,类所属的包名等等。所以当打印Date.getClass()时打印出的就是Date的访问属性,Date的所属包名。
Class类的三种实例化方式:
1.对象.getClass();//取得Class对象
2.类名.class;//可以直接根据某个具体类来取得其Class对象
3.调用Class类的静态方法Class.forName(String className)传入类的全名称来取得其Class对象。
比如:Class> cls = Class.forName(“java.util.Date”);
使用:
Class> cls1 = date.getClass();
Class> cls = Class.forName("java.util.Date");
Class> cls2 = Date.class;
Class类对象可以通过反射实例化对象。
方法:
public T newInstance() throws InstantiationException,IllegalAccessException
使用:
Object obj = cls.newInstance();
就相当于new了一个对象
Class类对象能干什么
得到Class对象,就可以根据对象获取到类中的变量,方法,构造等信息。获取这些信息有相应的方法。
反射与类的操作
取得类的包名称:public Package getPackage()
取得父类的Class对象:public native Class super T>getSuperclass();
取得实现的父接口:public Class>[] getInterfaces()
Class> cls = Watermelon.class;
System.out.println(cls.getPackage().getName());//包名
System.out.println(cls.getSuperclass().getName());//父类名
Class>[] str = cls.getInterfaces();
for(Class> str1:str){
System.out.printf(str1.getName());//父接口名
}
反射调用类中构造方法
取得类中指定参数类型的构造
public Constructor getConstructor(Class>… parameterTypes) throws NoSuchMethodException, SecurityException
只能取得类中public权限的构造方法
public Constructor getDeclaredConstructor(Class>… parameterTypes)
可以取得类中全部构造方法,包含私有构造
取得类中所有构造方法
public Constructor>[] getConstructors() throws SecurityException
只能取得类中public权限的构造方法
public Constructor>[] getDeclaredConstructors() throws SecurityException
可以取得类中全部构造方法,包含私有构造
举例:
class Person{
public Person(){};
public Person(int n){ };
public Person(String name,int age){};
private Person(String name,String name1){};
}
public class Test{
public static void main(String[] args) throws Exception {
//1.取得Class类的对象
Class> cls = Person.class;
//取得类中所有public权限的构造
System.out.println("getConstructors();取得类中所有public权限构造");
Constructor>[] constructors = cls.getConstructors();
for(Constructor> constructor : constructors){
System.out.println(constructor);
}
//取得类中全部构造
System.out.println("getDeclaredConstructors();取得类中所有构造");
constructors = cls.getDeclaredConstructors();
for(Constructor> constructor :constructors){
System.out.println(constructor);
}
//取得类中指定参数构造,public权限
System.out.println("getConstructor(String.class,int.class);取得指定参数的构造,public权限");
Constructor> constructor = cls.getConstructor(String.class,int.class);
System.out.println(constructor);
//取得类中指定参数构造,所有权限
System.out.println("getDeclaredConstructor(String.class,String.class);取得指定参数的构造,所有权限");
constructor = cls.getDeclaredConstructor(String.class,String.class);
System.out.println(constructor);
}
}
结果:
getConstructors();取得类中所有public权限构造
public www.bit.java.Person(java.lang.String,int)
public www.bit.java.Person(int)
public www.bit.java.Person()
getDeclaredConstructors();取得类中所有构造
private www.bit.java.Person(java.lang.String,java.lang.String)
public www.bit.java.Person(java.lang.String,int)
public www.bit.java.Person(int)
public www.bit.java.Person()
getConstructor(String.class,int.class);取得指定参数的构造,public权限
public www.bit.java.Person(java.lang.String,int)
getDeclaredConstructor(String.class,String.class);取得指定参数的构造,所有权限
private www.bit.java.Person(java.lang.String,java.lang.String)
可以使用Constructor类实例化对象
class Person{
private String name;
private int age;
public Person(String name,int age) {
this.name = name;
this.age = age;
};
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test{
public static void main(String[] args) throws Exception {
//1.取得Class类的对象
Class> cls = Person.class;
Constructor> constructor = cls.getConstructor(String.class,int.class);
System.out.println(constructor.newInstance("abaka",21));
}
}
结果:
Person{name=‘abaka’, age=21}
反射调用普通方法
取得类中指定名称的普通方法
public Method getMethod(String name, Class>… parameterTypes)
//方法有重载所以要传名称和参数类型取得本类以及父类中所有public方法
public Method getDeclaredMethod(String name, Class..parameterTypes)
取得本类中全部普通方法,包括私有方法
取得类中全部普通方法
public Method[] getMethods() throws SecurityException
取得本类以及父类中所有public方法
public Method[] getDeclaredMethods() throws SecurityException
取得本类中全部普通方法,包括私有方法
Method类中提供调用类中普通方法的API
public Object invoke(Object obj, Object… args)//具体对象, 具体对象的值
//1.取得Class类的对象
Class> cls = Person.class;
//2.取得本类以及父类中所有public方法
Method[] methods = cls.getMethods();
for(Method method:methods){
System.out.println(method);
}
应用:
class Person{
private String name;
private int age;
public void setName(String name){
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test{
public static void main(String[] args) throws Exception {
//1.取得Class类的对象
Class> cls = Person.class;
//2.创建Person实例化对象
Person person = (Person)cls.newInstance();
//3.取得方法,拿到setName的Method对象
Method method = cls.getMethod("setName",String.class);
Method method1 = cls.getMethod("setAge", int.class);
//4.通过invoke进行调用
method.invoke(person,"abaka");
method1.invoke(person,21);
System.out.println(person);
}
}
反射调用类中属性Filed
取得类中指定属性
public Field getField(String name)throws NoSuchFieldException, SecurityException
取得本类以及父类中所有public属性
public Field getDeclaredField(String name)throws NoSuchFieldException, SecurityException
取得本类中全部普通属性,包含私有属性。
取得类中全部属性
public Field[] getFields() throws SecurityException
public Field[] getDeclaredFields() throws SecurityException
设置属性
public void set(Object obj, Object value)
取得属性
public Object get(Object obj) throws IllegalArgumentException,IllegalAccexxException
取得属性的类型
public Class> getType()
使用:
//1.先创建class对象Class> cls = Person.class;
//2.创建Person实例化对象
Person person = (Person)cls.newInstance();
Field field = cls.getField("name");
field.set(person,"abaka");
System.out.println(field.get(person));