第21 章 : 认识反射机制
99 反射机制简介
Java的精髓所在
动态获取信息以及动态调用对象方法的功能
所有技术实现的目标只有一点:重用性
正:类 -> 实例对象
反:实例对象 -> 类
找到对象的根源
Object.getClass()
100 Class类对象的三种实例化模式
public final class Class<T> implements java.io.Serializable,
GenericDeclaration,
Type,
AnnotatedElement
要实例化的类
class Person{}
1、Object类支持
Object类可以根据实例化对象获取Class对象
缺点:
如果想获得类对象,则必须产生指定类对象后才能获得
Person person = new Person();
Class cls = person.getClass();
System.out.println(cls.getName());
// Person
2、JVM直接支持
采用类.class
直接实例化
如果要采用这种模式,则必须导入程序所对应开发包
Class cls = Person.class;
System.out.println(cls.getName());
// Person
3、Class类支持
Class类中提供了static方法
public static Class<?> forName(String className)
特点:
直接使用字符串形式定义要使用的类型,
程序不需要编写import,不存在则抛出异常
Class cls = Class.forName("Person");
System.out.println(cls.getName());
// Person
第22 章 : 反射应用案例
101 反射实例化对象
获取Class对象意义:
Class对象提供有一个对象的反射实例化方法
1、JDK<1.9
public T newInstance()
// 等价于关键字new, 只能调用无参构造 JDK>=1.9之后弃用
示例
Class cls = Class.forName("Person");
System.out.println(cls.newInstance());
// Person@2503dbd3
2、JDK>=1.9
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
示例
Class cls = Class.forName("Person");
System.out.println(cls.getDeclaredConstructor().newInstance());
// Person@2503dbd3
任何情况下如果要实例化对象则一定要调用类中的构造方法
102 反射与工厂设计模式
工厂设计模式:
通过工厂类获取指定接口实例化对象
接口的主要作用是为不同的层提供有一个操作的标准
如果直接将一个子类设置为接口实例化操作,那么一定会有耦合
工厂设计模式解决子类与客户端的耦合问题
1、静态工厂设计模式
如果子类增加,工厂类一定要做出修改
解决一个子类实例化
IMessage
-NetMessage
-CloudMessage
Factory // 通过传入的参数获取子类
Client
interface IMessage {
public void send(String message);
}
class Message implements IMessage {
@Override
public void send(String message) {
System.out.println("发送: " + message);
}
}
class Factory {
private Factory() {
}
public static IMessage getInstance(String className) {
if ("Message".equalsIgnoreCase(className)) {
return new Message();
}
return null;
}
}
public class Demo {
public static void main(String[] args) {
IMessage message = Factory.getInstance("message");
message.send("nihao");
}
}
2、利用反射实现工厂设计模式
解决一个接口多个子类实例化
修改工厂类代码
class Factory {
private Factory() {
}
public static IMessage getInstance(String className) {
IMessage message = null;
try {
message = (IMessage)Class.forName(className).getDeclaredConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return message;
}
}
3、泛型反射实现工厂设计模式
解决所有接口子类实例化
class Factory {
private Factory() {
}
public static <T> T getInstance(String className, Class<T> clazz) {
T instance = null;
try {
instance = (T)Class.forName(className).getDeclaredConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return instance;
}
}
public class Demo {
public static void main(String[] args) {
IMessage message = Factory.getInstance("Message", IMessage.class);
message.send("nihao");
}
}
103 反射与单例设计模式
单例设计模式:
类的构造函数私有化,通过static方法获取实例化对象
-懒汉式
-饿汉式
class Singleton{
private static Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
public void print(){
System.out.println("Singleton");
}
}
class Demo{
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
instance.print();
}
}
多线程下执行,产生多个实例化对象
class Singleton{
private static Singleton instance = null;
private Singleton() {
System.out.println("Singleton " + Thread.currentThread().getName());
}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
public void print(){
System.out.println("Singleton print");
}
}
class Demo{
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
new Thread(()->{
Singleton instance = Singleton.getInstance();
instance.print();
}, "instance" + i).start();
}
/**
* 输出结果
* Singleton instance0
* Singleton instance1
* Singleton print
* Singleton instance2
* Singleton print
* Singleton print
*/
}
}
修改为同步处理
class Singleton{
// volatile 不使用副本
private static volatile Singleton instance = null;
private Singleton() {
System.out.println("Singleton " + Thread.currentThread().getName());
}
// synchronized不在函数上加,而是在内部代码块加,提高执行效率
public static Singleton getInstance(){
if(instance == null){
synchronized (Singleton.class){
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
public void print(){
System.out.println("Singleton print");
}
}
class Demo{
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
new Thread(()->{
Singleton instance = Singleton.getInstance();
instance.print();
}, "instance" + i).start();
}
/**
* 输出结果
* Singleton instance1
* Singleton print
* Singleton print
* Singleton print
*/
}
}
面试题:单例设计模式
1、实现饿汉式单例设计模式,构造函数私有化
2、Java中用到单例设计模式的类:
Runtime, Pattern, Spring框架
3、懒汉式单例设计模式的问题