资料视频:韩顺平-反射专题
OCP:开闭原则(设计模式)
对扩展开放,对修改是关闭的
对象类:
public class Cat {
private String name="asd";
public int age=10;
public Cat() {
}
public Cat(String name) {
this.name = name;
}
public void hi(){
System.out.println("hi~~~");
}
public void cry(){
System.out.println("cry cry~~~");
}
}
properties:
classfullpath=com.company.Cat
method=hi
public class ReflectionQuestion {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//1. 使用properties类,可以读写配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src\\re.properties"));
String classfullpath = properties.get("classfullpath").toString();
String methodName = properties.get("method").toString();
System.out.println("classfullpath = "+classfullpath);
System.out.println("method = "+methodName);
//1.加载类,返回Class类型的对象cls
Class cls = Class.forName(classfullpath);
//2. 通过cls得到需要加载的类com.company.Cat 的对象实例
Object o = cls.newInstance();
//3. 通过cls得到想要加载的类Cat的methodName“hi”的方法对象
//反射中方法也被视为对象
Method method1 = cls.getMethod(methodName);
//4. 通过method1调用方法:即通过方法对象来实现调用方法
method1.invoke(o);//传统方法:对象的实例.方法(),反射机制:方法.invoke(对象的实例)
//通过cls得到你加载的类com.company.Cat
// System.out.println(o.getClass());
}
}
输出:
classfullpath = com.company.Cat
method = hi
hi~~~
== cls是加载类,o是对象实例,method1是方法对象==
改变properties
classfullpath=com.company.Cat
method=cry
输出也会改变:
classfullpath = com.company.Cat
method = cry
cry cry~~~
但是我们并没有改变代码,只是改变了properties
注意一点:Class类对象是一个对象,存在于堆中
XXX a=new XXX()
堆:存放对象实例new XXX(), 栈:存放地址信息 a,方法区(静态区):程序中唯一的元素,如class、static
Cat类的字节码二进制数据在方法区
类对象不是类而是对象,所以不在方法区,而是在堆中
//java.lang.reflect.Field
//反射获取类的属性值
//getField不能获取私有属性
Field age = cls.getField("age");
System.out.println(age.get(o));//传统方法:对象.成员变量(),反射机制:成员变量.get(对象的实例)
//java.lang.reflect.Field
Constructor constructor = cls.getConstructor();
System.out.println(constructor);
Constructor constructor2 = cls.getConstructor(String.class);
System.out.println(constructor2);
反射调优:
public class Reflection02 {
public static void main(String[] args) throws Exception {
Reflection02 reflection02 = new Reflection02();
reflection02.m1();
reflection02.m2();
reflection02.m3();
}
public void m1(){
Cat cat = new Cat();
long start = System.currentTimeMillis();
for (int i = 0; i < 90000000; i++) {
cat.hi();
}
long end = System.currentTimeMillis();
System.out.println("传统方法时间 = "+(end-start));
}
public void m2() throws Exception {
Class cls = Class.forName("com.company.Cat");
Object o = cls.newInstance();
Method hi = cls.getMethod("hi");
long start = System.currentTimeMillis();
for (int i = 0; i < 90000000; i++) {
hi.invoke(o);
}
long end = System.currentTimeMillis();
System.out.println("反射方法时间 = "+(end-start));
}
public void m3() throws Exception {
Class cls = Class.forName("com.company.Cat");
Object o = cls.newInstance();
Method hi = cls.getMethod("hi");
//在反射调用方法时,取消访问检查
hi.setAccessible(true);
long start = System.currentTimeMillis();
for (int i = 0; i < 90000000; i++) {
hi.invoke(o);
}
long end = System.currentTimeMillis();
System.out.println("反射调优时间 = "+(end-start));
}
}
传统方法时间 = 2
反射方法时间 = 111
反射调优时间 = 90
Class也是类,继承了Object类
Class类不是new出来的,是系统创建出来的
对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
//3.对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
Class aClass = Class.forName("com.company.Cat");
Class aClass2 = Class.forName("com.company.Cat");
System.out.println(aClass2==aClass);//true
public class Class02 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
String classAllPath="com.company.Cat";
Class aClass = Class.forName(classAllPath);
System.out.println(aClass);//class com.company.Cat,是哪个类的Class对象
System.out.println(aClass.getClass());//输出运行类型 java.lang.Class
System.out.println("=====================");
//得到包名 com.company
System.out.println(aClass.getPackage().getName());
//得到全类名 com.company.Cat
System.out.println(aClass.getName());
//通过aClass创建对象
Cat cat = (Cat)aClass.newInstance();
System.out.println(cat);
System.out.println("=====================");
//通过反射获取属性 共有属性
Field age = aClass.getField("age");
System.out.println(age.get(cat));//10
//通过反射给属性赋值
age.set(cat,18);
System.out.println(age.get(cat));//18
//得到所有属性
Field[] fields = aClass.getFields();
for (Field f:fields){
System.out.println(f.getName());
}
}
}
class com.company.Cat
class java.lang.Class
=====================
com.company
com.company.Cat
com.company.Cat@1b6d3586
=====================
10
18
age
四种方式获取Class对象
得到的Class对象都是同一个
public class GetClass_ {
public static void main(String[] args) throws ClassNotFoundException {
String classAllPath="com.company.Cat";
//四种方式获取Class对象
Class aClass = Class.forName(classAllPath);
System.out.println(aClass);
Class aClass2= Cat.class;
System.out.println(aClass2);
Cat cat = new Cat();
Class aClass3 = cat.getClass();
System.out.println(aClass==aClass2);//true
System.out.println(aClass==aClass3);//true
//通过类加载器获得类的Class对象
ClassLoader classLoader = cat.getClass().getClassLoader();
Class aClass4 = classLoader.loadClass(classAllPath);
System.out.println(aClass==aClass4);//true
}
}
几种基本类型的Class对象
Class<Integer> integerClass = int.class;
Class<Integer> integerClass1 = Integer.class;
Class<String> stringClass = String.class;
Class<Boolean> booleanClass = boolean.class;
Class<Integer> type = Integer.TYPE;
Class<Character> type1 = Character.TYPE;
System.out.println(integerClass==type);//true
动态和静态加载
我们发现有一个new Dog(),它会直接编译报错,这是静态加载
case 2 中,只有“Person”字符串,并没有写Person,我们编译的是Class.forName(),并没有加载Person,
只有在我们key=2的时候,我们去找Person类,然后加载它,运行的时候才会用它,即使没有Person类,只要不运行它,就不会报错
类加载流程图
- 加载:ClassLoader()
- 验证:验证字节码和一些安全方面的东西
- 准备:静态变量默认初始化
- 解析:符号引用转为直接引用
- 初始化:程序员写的代码,对静态变量进行初始化赋值
连接阶段-准备
- JVM会在该阶段对静态变量,分配内存并默认初始化
class B{
static {
System.out.println("静态代码块已执行");
num=100;
}
static int num=300;
public B(){
System.out.println("构造方法已执行");
}
}
当我们new B()的时候
- 加载B类,并生成B的class对象
- 链接 num=0
- 初始化阶段 -依次自动收集类中的所有静态变量的赋值动作和静态代码块,并合并
clinit(){
System.out.println(“静态代码块已执行”);
//合并num为100
num=300;
num=100;
} - 执行构造器
加载类的时候会加锁
保证每个类的Class类对象只有一个
获取类结构信息
public class ReflectionUtils {
public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
Class personCls = Class.forName("com.company.reflection.Person");
System.out.println(personCls.getName());
System.out.println(personCls.getSimpleName());
Field[] fields = personCls.getFields();
for (Field field : fields) {
System.out.println(field.getName());
}
System.out.println("===========================");
Field[] declaredFields = personCls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName());
}
System.out.println("==========获取本类所有方法===========");
Method[] methods = personCls.getMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
System.out.println("==========获取本类构造方法(公有的)===========");
Constructor[] constructors = personCls.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor.getName());
}
System.out.println("==========获取本类所有构造方法(包括私有)===========");
Constructor[] declaredConstructors = personCls.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor.getName());
}
System.out.println("=============================");
System.out.println(personCls.getPackage());
System.out.println(personCls.getSuperclass());
Class[] interfaces = personCls.getInterfaces();
for (Class anInterface : interfaces) {
System.out.println(anInterface);
}
Annotation[] annotations = personCls.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}
class A{
public String hobby;
public void AAA(){
}
}
interface IA{
}
interface IB{
}
@Deprecated
class Person extends A implements IA,IB{
public String name;
protected int age;
String job;
private double sal;
public Person() {
}
private Person(String name) {
this.name = name;
}
public void m1(){
}
protected void m2(){
}
void m3(){
}
private void m4(){
}
}
com.company.reflection.Person
Person
name
hobby
===========================
name
age
job
sal
==========获取本类所有方法===========
m1
AAA
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll
==========获取本类构造方法===========
com.company.reflection.Person
==========获取本类所有构造方法(包括私有)===========
com.company.reflection.Person
com.company.reflection.Person
=============================
package com.company.reflection
class com.company.reflection.A
interface com.company.reflection.IA
interface com.company.reflection.IB
@java.lang.Deprecated()
Field和Method都有getModifiers()方法
反射可以访问私有属性,构造器
public class ReflecCreateInstance {
public static void main(String[] args) throws Exception {
Class userClass = Class.forName("com.company.reflection.User");
//通过public的无参构造创建实例
Object o = userClass.newInstance();
System.out.println(o);
//通过public有参构造器创建实例
//先得到构造器
Constructor constructor = userClass.getConstructor(String.class);
//创建实例,并传入实参
User o1 =(User) constructor.newInstance("你好");
System.out.println(o1);
//通过非public的有参构造器创建实例
//得到private构造器
Constructor declaredConstructor = userClass.getDeclaredConstructor(int.class, String.class);
declaredConstructor.setAccessible(true);//暴力破解
//创建对象
Object hello = declaredConstructor.newInstance(11, "hello");
System.out.println(hello);
}
}
class User{
private int age;
private String name;
public User() {
}
public User(String name) {
this.name = name;
}
private User(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
访问静态属性和方法
public class ReflecAccessProperty {
public static void main(String[] args) throws Exception {
Class<?> stuClass = Class.forName("com.company.reflection.Student");
Object o = stuClass.newInstance();
System.out.println(o);
//反射获取age属性
Field age = stuClass.getField("age");
//反射操作属性
age.set(o,11);
System.out.println(o);
System.out.println(age.get(o));
//使用反射操作name
Field name = stuClass.getDeclaredField("name");
name.setAccessible(true);
// name.set(o,"hhh");
//只有静态属性才可以写null
name.set(null,"hhh");
System.out.println(name.get(null));
}
}
class Student{
public int age;
private static String name;
public Student() {
}
@Override
public String toString() {
return "Student{" +
"age=" + age +","+
"name=" + name +
'}';
}
}
爆破
public class ReflecAccessMethod {
public static void main(String[] args) throws Exception {
Class<?> bossClass = Class.forName("com.company.reflection.Boss");
Object o = bossClass.newInstance();
//调用普通方法 只能获取public
Method hi = bossClass.getMethod("hi",String.class);
//可以获取private
hi = bossClass.getDeclaredMethod("hi",String.class);
Object jiaoyu = hi.invoke(o, "jiaoyu");
System.out.println(jiaoyu);//null
Method say = bossClass.getDeclaredMethod("say", int.class, String.class, char.class);
//因为say是私有的,需要爆破
say.setAccessible(true);
System.out.println(say.invoke(o,666,"hhh",'q'));
//返回值
System.out.println(say.getReturnType());
}
}
class Boss{
public int age;
private static String name;
public Boss() {
}
private static String say(int n, String s, char c){
return n+" "+s+" "+c;
}
public void hi(String s){
System.out.println("hi "+s);
}
}