Java 反射reflect及其他

反射,是一个相对底层的内容。
未来这个内容你几乎不自己写?为什么呢?
因为你会用各种框架,框架的底层实现就是反射。

学习今天的内容,能帮你理解框架的实现机制。为以后学框架打基础。

类加载器
反射
动态代理(先讲代理设计模式,再讲动态代理)

//类(我们自己写的类以及系统提供的类)是怎么加载到内存中的?
加载类(.class文件)的过程:
1、JVM读取.class文件,并进行校验文件的正误
2、加载你的静态属性或者静态方法
3、初始化对象(初始化块、构造方法的执行)。

什么时候加载一个类呢?
1、创建对象的时候(首次创建的时候才加载这个类)。Person p = new Person();
2、使用静态属性的时候(赋值以及取值) Person.count = 100;
3、调用静态方法的时候
4、当创建子类对象的时候(你是父类)。

系统用什么加载的类呢?----类加载器。
类加载器的作用:把.class文件读入内存。//这个过程就是加载。

在java中一共有3种类加载器
Bootstrap ClassLoader 根加载器(加载系统的核心类库 rt.jar),无法获取
Extension ClassLoader 扩展类加载器(加载扩展的jar包ext文件夹下面的所有jar包)
System ClassLoader 系统类加载器(就是你自己写的类,用这个加载器。
你配置的classPath环境变量所指向的位置。)

反射:
普通类是描述对象的。Person类,用于描述每一个Person对象应该有哪些属性和方法。

你可能有很多个类,例如:String,Person,ArrayList,InputStreamReader
//上述的所有类,都有共性,都有行为,都有属性
如果要描述这些类,应该怎么描述呢?使用Class类
Class类:用来描述类的类,可以描述这个类有几个属性,有几个方法,几个构造放,几个接口。。。
在Java变成语言里,任何数据类型(包括基本数据类型)都有一个Class对象描述它。

想要深入学习Class类,第一件事就获取一个Class类型的对象。

获取Class对象有3种方式
方式1:类名.class属性
方式2:对象.getClass()方法
方式3:Class.forName(“类名(含包名)”)

什么是反射呢?
在程序运行过程中,一旦你知道一个类(类名),你就可以获取这个类的所有属性和方法
同时,你还可以创建这个类的对象以及调用所有属性(包括私有的)和所有方法(包括私有的)。
这套机制就叫反射。

反射的基础就是Class对象。有了Class对象才能做你想实现的功能。


回顾总结
反射(reflect):
在程序运行过程中(运行期),如果你知道一个类的名字,你可以
获取这个类的全部属性和方法,并且能够访问属性和方法。

实际上反射可以访问:
属性(Field):public、默认的、protected、private修饰的
成员属性以及类属性(static)。
//批量获取属性:
//(1)获取所有的public属性(含父类继承过来的)。
getFields()
//(2)获取所有的属性(切记:不含继承的)
getDeclaredFields()
//(3)获取指定的public属性(含父类继承过来的)
getField(String fieldName)
//(4)获取指定的属性(切记:不含继承的)
getDecalaredField(String fieldName)

方法(Method):public、默认的、protected、private修饰的方法
//(1)获取所有public方法(含父类继承过来的)
//(2)获取所有方法(切记:不含继承的)
//(3)获取指定的public方法(含父类继承过来的)
//(4)获取指定的方法(切记:不含继承的)
构造器(Constructor):public、默认的、protected、private
//(1)获取所有public构造方法
//(2)获取所有的构造方法
//(3)获取指定的public构造方法
//(4)获取指定的构造方法

父类(Class):父类也是一个Class。
接口(Class):Java中接口被当作Class来处理了。
获取泛型
获取注解

反射的用途:
(1)访问你的私有属性和方法。
第一步:获取私有属性或方法
第二步:设置属性或方法的setAccessable为true。(关闭JVM对访问修饰符的检查)
第三步:设置属性或调用方法
(2)绕过泛型的检查
第一步:获取要使用的方法(Method)
第二步:调用方法
(3)很多框架都是通过读文件(例如:XML文件、properties文件)让你的代码更灵活。

反射的应用:动态(Dynamic)代理(Proxy)
代理?----设计模式
动态代理?

//

package com.lanou3g.proxy;

public interface BossInterface {
public abstract void meet();	//见面
public abstract void consume();	//消费
}

//

package com.lanou3g.proxy;

public class CoalBoss implements BossInterface{

@Override
public void meet() {
	System.out.println("煤老板在见面");
	
}

@Override
public void consume() {
	System.out.println("煤老板在消费");
	
  }
}

//

package com.lanou3g.proxy;

public class CoalBossProxy implements BossInterface {

private CoalBoss boss;



public CoalBossProxy(CoalBoss boss) {
	super();
	this.boss = boss;
}

@Override
public void meet() {
	
	System.out.println("见面前的一些准备工作");
	boss.meet();
	System.out.println("做见面后的事宜");
	
}

@Override
public void consume() {
	
	System.out.println("提前预定。。。");
	boss.consume();
	System.out.println("买单");
	
}
}

//

package com.lanou3g.proxy;

import java.lang.reflect.Proxy;

public class Test {

public static void main(String[] args) {
	
	CoalBoss cb = new CoalBoss();
//		cb.consume();
//		cb.meet();
	
	CoalBossProxy cbp = new CoalBossProxy(cb);
	cbp.meet();
	cbp.consume();
	}
	}

自动代理

package com.lanou3g.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicProxy implements InvocationHandler {

private Object target;	//目标对象----需要使用代理的对象。
//(例如:煤老板(CoalBoss)、钢铁老板等)

public DynamicProxy(Object target) {
	super();
	this.target = target;
}


//获取代理对象。
public Object newProxy() {
	return Proxy.newProxyInstance(
			target.getClass().getClassLoader(),
			target.getClass().getInterfaces(),
			this);
}


//代理对象 调用接口中的方法时,会执行下面的代码。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	
	System.out.println("前期的处理代码");
	Object o = method.invoke(target, args);//原始方法的执行
	System.out.println("后续的处理代码");
	
	return o;
}
}

//

package com.lanou3g.proxy;

public interface Interface1 {
public abstract void test();
}

//

package com.lanou3g.proxy;

public class A implements Interface1 {

@Override
public void test() {
	System.out.println("测试动态代理好不好用");

}
}

//

package com.lanou3g.proxy;

public class TestProxy {

public static void main(String[] args) {
	A a = new A();
	DynamicProxy dp3 = new DynamicProxy(a);
	Interface1 proxy = (Interface1) dp3.newProxy();
	proxy.test();

}
}

猜你喜欢

转载自blog.csdn.net/weixin_43791238/article/details/89322100
今日推荐