为什么要使用反射呢
一般情况下的程序对象是自己new的,程序相当于写死了给jvm去跑。但是,如果一个服务器上突然遇到某个请求哦要用到某个类,哎呀但没加载进jvm,是不是要停下来自己写段代码,new一下,启动一下服务器,(脑残?)!
反射是什么呢?当我们的程序在运行时,需要动态的加载一些类这些类可能之前用不到所以不用加载到jvm,而是在运行时根据需要才加载,这样的好处对于服务器来说不言而喻,举个例子我们的项目底层有时是用mysql,有时用oracle,需要动态地根据实际情况加载驱动类,这个时候反射就有用了,假设 com.java.dbtest.myqlConnection,com.java.dbtest.oracleConnection这两个类我们要用,这时候我们的程序就写得比较动态化,通过Class tc = Class.forName(“com.java.dbtest.TestConnection”);通过类的全类名让jvm在服务器中找到并加载这个类,而如果是oracle则传入的参数就变成另一个了。这时候就可以看到反射的好处了,这个动态性就体现出java的特性了!举多个例子,大家如果接触过spring,会发现当你配置各种各样的bean时,是以配置文件的形式配置的,你需要用到哪些bean就配哪些,spring容器就会根据你的需求去动态加载,你的程序就能健壮地运行。
简单理解就是不再直接new对象了,而是间接的获取class对象
类加载器把 .java 文件通过编译之后变成了 .class 文件。可知.clsss 字节码文件是拥有 .java 文件的所有东西。
一个java程序的加载就是把所对应的 .class 文件加载到内存的方法区,在内存中有一个 .class 文件对应的内存区域,这个内存区域包含了java所有的内容(成员变量,成员方法,构造方法等)
获取类对象的三种方法
1、static Class forName(String name):通过类名来获取,是静态方法,传入的参数是一个完整的(包名+类名)
2、Class类名.class:通过类名来调用,获取当前类对应的属性
3、Class类对象.getClass():通过类对象来调用,获取当前Class类对象
public class Reflect {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println("这个人是:"+person.name);
//方式一:通过对象获得
Class c1 = person.getClass();
System.out.println(c1.hashCode());
//方式二:forname获得
Class c2 = Class.forName("com.qfedu.Student");
System.out.println(c2.hashCode());
//方式三:通过类名.class获得
Class c3 = Student.class;
System.out.println(c3.hashCode());
}
}
class Person{
public String name;
public Person(){
}
public Person(String name){
this.name=name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
class Student extends Person{
public Student(){
this.name="学生";
}
}
class Teacher extends Person{
public Teacher(){
this.name="老师";
}
## 获取Constructor类对象
Constructor[] getConstructors();获取当前类内所有的非私有化的构造方法
Constructor[] getDeclaredConstructors();获取当前类所有的构造方法,包括私有
Constructor getConstructor(Class…initParmeterType);根据指定的参数类型获得相应的非私有化方法
Constructor getDeclaredConstructor(Class…initParmeterType)根据指定的参数类型获得相应的构造方法,包含私有的
Object newInstance(Object…initParmeters)获取当前类的对象
public class GetConstructors {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> aClass = Class.forName("com.qfedu.reflect.Person");
Constructor<?>[] constructors = aClass.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);//3
}
System.out.println("===========");
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);//4
}
System.out.println("======");
Constructor<?> constructor = aClass.getConstructor(null);
System.out.println(constructor);//无参数的构造
Constructor<?> constructor1 = aClass.getConstructor(int.class);
System.out.println(constructor1);//int类型构造方法
Constructor<?> constructor2 = aClass.getConstructor(String.class);
System.out.println(constructor2);
Constructor<?> constructor3 = aClass.getDeclaredConstructor(int.class, String.class);
System.out.println(constructor3);
System.out.println("======");
Object o = constructor.newInstance(null);
System.out.println(o);
Object o1 = constructor1.newInstance(10);
System.out.println(o1);
System.out.println("======");
constructor3.setAccessible(true);//暴力反射获取反射的内容,私有的不能进行赋值
//setAccessible(true)
Object laoxing = constructor3.newInstance(3, "Laoxing");
System.out.println(laoxing);
}
获取Method类对象
Method[] getMethods();获取当前类的非私有化成员方法,包括从父类继承过来在子类可以使用的方法
Method[] getDeclaredMethods();获取当前类所有的成员方法,但不包括从父类继承过来的在子类可以使用的方法
Method[] getMethod(String methodName,Class...parameterType);获取类内指定的方法,和参数类型的非私有化方法
Method[] getDeclaredMethod(String methodName,Class...parameterType);获取类内指定的方法,和参数类型的方法,包括了私有化的方法
Object invoke(Object obj,Object...args)
Object obj:调用当前方法的类对象
Object...args:执行当前方法的需要的实际参数列表
public class GetMethodsObject {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> aClass = Class.forName("com.qfedu.reflect.Person");
Method[] methods = aClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("=========");
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("===========");
Method game = aClass.getMethod("game", null);
System.out.println(game);
Method game1 = aClass.getMethod("game", String.class);
System.out.println(game1);
System.out.println("========");
Method testPrivate = aClass.getDeclaredMethod("testPrivate", null);
Method testPrivate1 = aClass.getDeclaredMethod("testPrivate", String.class);
System.out.println(testPrivate);
System.out.println(testPrivate1);
System.out.println("-===========");
Person person = new Person();
System.out.println(person);
Object o = aClass.getConstructor(null).newInstance(null);
System.out.println(o);
game.invoke(o, null);//这个方法必须得会!!!
game1.invoke(aClass.getConstructor(null).newInstance(null), "我无敌了,你们随便送!!!");
testPrivate.setAccessible(true);
testPrivate.invoke(aClass.getConstructor(null).newInstance(null), null);
testPrivate1.setAccessible(true);
testPrivate1.invoke(aClass.getConstructor(null).newInstance(null), "heheda");
}
}
获取Field类对象
Field[] getFields();获取非私有化成员属性的类对象。返回的是一个数组
Field[] getDeclaredFields();获取所有成员属性的类对象。包含私有的,返回的是一个数组
Field getField(String FieldName);通过成员变量的名字获取指定的成员变量,不能获取私有的成员变量
Field getDeclaredField(String FieldName);通过成员变量的名字获取指定的成员变量,可以获取私有化的成员变量
void set(Object obj,Object value);给当前对象的属性进行赋值
Object get(Object obj);获取类对象属性的值
public class GetFieldObject {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> aClass = Class.forName("com.qfedu.reflect.Person");
Field[] fields = aClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("========");
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println("======");
Field test = aClass.getField("test");
System.out.println(test);//非私有化的成员变量
Field id = aClass.getDeclaredField("id");
System.out.println(id);
//获取Person对象
Person person = (Person)aClass.getConstructor(null).newInstance(null);
id.setAccessible(true);
id.set(person, 20);
test.set(person, 100);
System.out.println(person);
System.out.println(id.get(person));
}
}