-
反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息(比如成员变量,构 造器,成员方法等等),并能操作对象的属性及 方法。反射在设计模式和框架底层都会用到
-
加载完类之后,在堆中就产生了一个Class类型 的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个Class对象就像一面镜子,透过这个镜子看到类的结构,所以形象的称之 为反射
-
p 对象 --> 类型Person类
Class 对象 cls —>类型Class类
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时得到任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的成员变量和方法
- 生成动态代理
- java.Iang.Class:代表一个类,Class对象表示某个类加载后在堆中的对象
- java.Iang.reflect.Method:代表类的方法,Method对彖表示某个类的方法
- java.lang.reflect.Field:代表类的成员变量,Field对象表示某个类的成员变量
- java.Iang.reflect.Constructor:代表类的构造方法,Constructor对象表示构造器
- 这些类在 java.lang.reflection
package reflection;
import reflection.quession.Cat;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
@SuppressWarnings({"all"})
public class Reflection01 {
public static void main(String[] args) throws Exception {
//1. 使用Properties 类, 可以读写配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src\re.properties"));
String classfullpath = properties.get("classfullpath").toString();//"com.hspedu.Cat"
String methodName = properties.get("method").toString();//"hi"
//2. 使用反射机制解决
//(1) 加载类, 返回Class类型的对象cls
Class cls = Class.forName(classfullpath);
//(2) 通过 cls 得到你加载的类 com.hspedu.Cat 的对象实例
Object o = cls.newInstance();
System.out.println("o的运行类型=" + o.getClass()); //运行类型
//(3) 通过 cls 得到你加载的类 com.hspedu.Cat 的 methodName"hi" 的方法对象
// 即:在反射中,可以把方法视为对象(万物皆对象)
Method method1 = cls.getMethod(methodName);
//(4) 通过method1 调用方法: 即通过方法对象来实现调用方法
System.out.println("=============================");
method1.invoke(o); //传统方法 对象.方法() , 反射机制 方法.invoke(对象)
//java.lang.reflect.Field: 代表类的成员变量, Field对象表示某个类的成员变量
//得到name字段
//getField不能得到私有的属性
Field nameField = cls.getField("age"); //
System.out.println(nameField.get(o)); // 传统写法 对象.成员变量 , 反射 : 成员变量对象.get(对象)
//java.lang.reflect.Constructor: 代表类的构造方法, Constructor对象表示构造器
Constructor constructor = cls.getConstructor(); //()中可以指定构造器参数类型, 返回无参构造器
System.out.println(constructor);//Cat()
Constructor constructor2 = cls.getConstructor(String.class); //这里老师传入的 String.class 就是String类的Class对象
System.out.println(constructor2);//Cat(String name)
}
}
反射优缺点
- 优点:可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就失去底层支撑。
- 缺点:使用反射基本是解释执行,对执行速度有影响.
注: Method和Field、Constructor对象都有setAccessible方法
- setAccessible作用是启动和禁用访问安全检查开关
- 参数值为true表示反射的对象在使用时取消访问检查,提高反射的效率。参数值 为false则表示反射的对象执行访问检查
1.Class也是类,因此也继承Object类
2. Class类对象不是new出来的,而是系统创建的
3. 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
4.每个类的实例都会记得自己是由哪个Class实例所生成
5. 通过Class对象可以完整地得到一个类的完整结构,通过一系列API
6. Class对象是存放在堆的
7. 类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据(包括方法代码, 变量名,方法名,访问权限等等)https://www.zhihu.com/question/38496907
package reflection.class_;
public class Class01 {
public static void main(String[] args) throws ClassNotFoundException {
//看看Class类图
//1. Class也是类,因此也继承Object类
//Class
//2. Class类对象不是new出来的,而是系统创建的
//(1) 传统new对象
//Cat cat = new Cat();
//(2) 反射方式, 没有debug到 ClassLoader类的 loadClass, 原因是,我没有注销Cat cat = new Cat();
Class cls1 = Class.forName("reflection.quession.Cat");
//3. 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
Class cls2 = Class.forName("reflection.quession.Cat");
System.out.println(cls1.hashCode());
System.out.println(cls2.hashCode());
Class cls3 = Class.forName("reflection.quession.Cat");
System.out.println(cls3.hashCode());
}
}
Class对应方法
package reflection.class_;
import reflection.Car;
import java.io.File;
import java.lang.reflect.Field;
//"reflection.quession.Cat"
@SuppressWarnings({"all"})
public class Class02 {
public static void main(String[] args) throws Exception {
String classAllPath = "reflection.Car";
//1 . 获取到Car类 对应的 Class对象
//> 表示不确定的Java类型
Class> cls = Class.forName(classAllPath);
//2. 输出cls
System.out.println(cls); //显示cls对象, 是哪个类的Class对象 com.hspedu.Car
System.out.println(cls.getClass());//输出cls运行类型 java.lang.Class
//3. 得到包名
System.out.println(cls.getPackage().getName());//包名
//4. 得到全类名
System.out.println(cls.getName());
//5. 通过cls创建对象实例
Car car = (Car) cls.newInstance();
System.out.println(car);//car.toString()
//6. 通过反射获取属性 brand
Field brand = cls.getField("brand");
System.out.println(brand.get(car));//宝马
//7. 通过反射给属性赋值
brand.set(car, "奔驰");
System.out.println(brand.get(car));//奔驰
//8 我希望大家可以得到所有的属性(字段)
System.out.println("=======所有的字段属性====");
Field[] fields = cls.getFields();
for (Field f : fields) {
System.out.println(f.getName());//名称
}
}
}
获取Class对象的各种方式
package reflection.class_;
import reflection.Car;
import java.util.zip.ZipEntry;
@SuppressWarnings({"all"})
public class GetClass_ {
public static void main(String[] args) throws Exception {
//1
String classAllPath = "reflection.Car";
//1. Class.forName
//通过读取配置文件获取
Class> cls1 = Class.forName(classAllPath);
System.out.println(cls1);
//2. 类名.class , 应用场景: 用于参数传递
Class cls2 = Car.class;
System.out.println(cls2);
//3. 对象.getClass(), 应用场景,有对象实例
Car car = new Car();
Class cls3 = car.getClass();
System.out.println(cls3);
//4. 通过类加载器【4种】来获取到类的Class对象
//(1)先得到类加载器 car
ClassLoader classLoader = car.getClass().getClassLoader();
//(2)通过类加载器得到Class对象
Class cls4 = classLoader.loadClass(classAllPath);
System.out.println(cls4);
//cls1 , cls2 , cls3 , cls4 其实是同一个对象
System.out.println(cls1.hashCode());
System.out.println(cls2.hashCode());
System.out.println(cls3.hashCode());
System.out.println(cls4.hashCode());
//5. 基本数据(int, char,boolean,float,double,byte,long,short) 按如下方式得到Class类对象
Class integerClass = int.class;
Class characterClass = char.class;
Class booleanClass = boolean.class;
System.out.println(integerClass);//int
//6. 基本数据类型对应的包装类,可以通过 .TYPE 得到Class类对象
Class type1 = Integer.TYPE;
Class type2 = Character.TYPE; //其它包装类BOOLEAN, DOUBLE, LONG,BYTE等待
System.out.println(type1);
System.out.println(integerClass.hashCode());//?
System.out.println(type1.hashCode());//?
}
}
哪些类型有 Clas 对象
package reflection.class_;
import java.io.Serializable;
@SuppressWarnings({"all"})
public class AllTypeClass {
public static void main(String[] args) {
Class cls1 = String.class;//外部类
Class cls2 = Serializable.class;//接口
Class cls3 = Integer[].class;//数组
Class cls4 = float[][].class;//二维数组
Class cls5 = Deprecated.class;//注解
Class cls6 = Thread.State.class; //枚举
Class cls7 = long.class;//基本数据类型
Class cls7_5 = Integer.class;//基本类型的包装类型
Class cls8 = void.class;//void数据类型
Class cls9 = Class.class;//
System.out.println(cls1);
System.out.println(cls2);
System.out.println(cls3);
System.out.println(cls4);
System.out.println(cls5);
System.out.println(cls6);
System.out.println(cls7);
System.out.println(cls7_5);
System.out.println(cls8);
System.out.println(cls9);
}
}
System.out.println(cls3);
System.out.println(cls4);
System.out.println(cls5);
System.out.println(cls6);
System.out.println(cls7);
System.out.println(cls7_5);
System.out.println(cls8);
System.out.println(cls9);
}
}



