Theme NexT works best with JavaScript enabled
0%

Java基础

^ _ ^

Java反射

什么是Java反射

Java反射就是通过Java类名获取该类Java字节码的机制。获取到字节码后可将字节码中的方法、变量、构造函数映射为相应的Method,Field,Constructor等类,这些类提供了丰富的方法供我们使用。

获取字节码的三种方法

  1. Class.forName(className)
  2. 类名.class
  3. this.getClass()

动态代理

写一个 ArrayList 的动态代理类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Solution {
final List<String> list = new ArrayList<String>();

List<String> proxyInstance = (List<String>) Proxy.newProxyInstance(list.getClass().getClassLoader(), list.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(list, args);
}
});

@Test
public void test01(){
proxyInstance.add("你好");
System.out.println(list);
}
}

写一个静态代理和动态代理的对比例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// 定义一个公共接口
interface AInterface{
void doSomething();
}

// 定义一个实现接口的客户类
class AClient implements AInterface{
@Override
public void doSomething() {
System.out.println("客户吃饭");
}
}

// 定义一个实现接口的静态代理类
class StaticProxy implements AInterface{
private AInterface client;

public StaticProxy(AClient client){
this.client = client;
}
@Override
public void doSomething() {
System.out.println("代理买饭");
client.doSomething();
System.out.println("代理洗碗");
}
}

// 动态代理类
class DynamicProxy{
private Object obj;
public DynamicProxy(Object obj){
this.obj = obj;
}
public Object getProxy(){
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), (proxy, method, args)->{
System.out.println("代理买饭");
Object result = method.invoke(obj, args);
System.out.println("代理洗碗");
return result;
});
}
}

public class Solution {
@Test
public void test01(){
AInterface proxy = new StaticProxy(new AClient());
proxy.doSomething();
}

@Test
public void test02(){
DynamicProxy dynamicProxy = new DynamicProxy(new AClient());
AInterface proxy = (AInterface)dynamicProxy.getProxy();
proxy.doSomething();
}
}

动静态代理的区别,什么场景使用?

静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。动态代理:在程序运行时,运用反射机制动态创建而成。因此,静态代理事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道。

AOP 编程就是基于动态代理实现的,比如著名的 Spring 框架、Hibernate 框架等等都是动态代理的使用例子。

动态代理的手段

  1. 实现 JDK 里的 InvocationHandler 接口的 invoke 方法,但注意的是代理的是接口,也就是你的业务类必须要实现接口,通过 Proxy 里的 newProxyInstance 得到代理对象。
  2. 还有一种动态代理 CGLIB ,代理的是类,不需要业务类继承接口,通过派生的子类来实现代理。通过在运行时,动态修改字节码达到修改类的目的。

设计模式

目的划分设计模式可分为三大类:

  1. 创建型模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”,共5种:工厂方法模式、抽象工厂模式、建造者模式、单例模式、原型模式。
  2. 行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。共11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
  3. 结构型模式:用于描述如何将类或对象按某种布局组成更大的结构,共7种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

作用范围划分设计模式可分为两大类:

  1. 类模式:用于处理类与子类之间的关系,这些关系通过继承来建立,是静态的,在编译时刻便确定下来了。共4种:工厂方法、(类)适配器、模板方法、解释器。
  2. 对象模式:用于处理对象之间的关系,这些关系可以通过组合或聚合来实现,在运行时刻是可以变化的,更具动态性。除了以上 4 种,其他的都是对象模式。

设计模式七大原则

创建型模式

抽象工厂

一个工厂下有一个产品族,比如一个电脑工厂下有键盘、鼠标、显示器这些产品组成的产品族。工厂也会有很多类型,如华硕、惠普、小米等。抽象工厂模式包含两层抽象:

  1. 产品的抽象,例如键盘接口下有各品牌键盘的实现类;
  2. 工厂的抽象,例如工厂接口下有各品牌工厂。工厂接口中包含生产键盘生产鼠标等函数定义,其实现类实现该函数时创建对应品牌该类产品。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// 鼠标
interface Mouse{
void introduce();
}

// MAC鼠标
class MACMouse implements Mouse{
private final String DESCRIPTION = "This is MAC mouse.";
@Override
public void introduce() {
System.out.println(DESCRIPTION);
}
}

// HP鼠标
class HPMouse implements Mouse{
private final String DESCRIPTION = "This is HP mouse.";
@Override
public void introduce() {
System.out.println(DESCRIPTION);
}
}

// 生产键盘
interface Keyboard{
void introduce();
}

// MAC键盘
class MACKeyboard implements Keyboard{
private final String DESCRIPTION = "This is MAC Keyboard.";
@Override
public void introduce() {
System.out.println(DESCRIPTION);
}
}

// HP键盘
class HPKeyboard implements Keyboard{
private final String DESCRIPTION = "This is HP Keyboard.";
@Override
public void introduce() {
System.out.println(DESCRIPTION);
}
}

// 抽象工厂
interface Factory{
Mouse createMouse();
Keyboard createKeyboard();
}

// 具体工厂 -- MAC工厂
class MACFactory implements Factory{
@Override
public Mouse createMouse() {
return new MACMouse();
}

@Override
public Keyboard createKeyboard() {
return new MACKeyboard();
}
}

// 具体工厂 -- HP工厂
class HPFactory implements Factory{
@Override
public Mouse createMouse() {
return new HPMouse();
}

@Override
public Keyboard createKeyboard() {
return new HPKeyboard();
}
}


// 制造工厂
class FactoryMaker{
public enum PCType{
MAC,HP
}

public Factory makeFactory(PCType pcType){
switch (pcType){
case HP:
return new HPFactory();
case MAC:
return new MACFactory();
default:
throw new IllegalArgumentException("PCType not supported.");
}

}
}


public class Solution {
@Test
public void test01(){
FactoryMaker factoryMaker = new FactoryMaker();

Factory macFactory = factoryMaker.makeFactory(FactoryMaker.PCType.MAC);
macFactory.createMouse().introduce();
macFactory.createKeyboard().introduce();

Factory hpFactory = factoryMaker.makeFactory(FactoryMaker.PCType.HP);
macFactory.createMouse().introduce();
macFactory.createKeyboard().introduce();
}
}

单例模式

指一个类只有一个实例。

1
2
3
enum Singleton{
INSTANCE
}