Chp22-反射
概念
是一种底层技术, 核心为通过操作类对象来实现最终的目的, 通常用于底层框架的编写
类对象
- 类对象:是类加载的产物, 内部存放着类的所有信息, 如包信息,父类信息,接口信息, 属性信息,方法信息,构造信息等, 只有一个
- 类的对象: 是类实例化的产物, 存储着对象的具体信息, 可以为0-n个
获取类对象-Class
-
getClass()
Class 引用名=实例对象引用名.getClass();
Student stu = new Student(); Class c1 = stu.getClass();
-
类名.class
Class<Student> c2 = Student.class;
-
Class.forName(“全限定名”)
try { Class c3 = Class.forName("com.by.entity.Student"); } catch (ClassNotFoundException e) { System.out.println("类加载异常!"); e.printStackTrace(); }
构建实例
-
利用无参构造
-
类对象.newInstance()
: 利用类对象中的无参构造构建类的实例对象//利用无参构造构建类的实例-类对象无泛型时需要强转 Student stu1=(Student) c1.newInstance(); Student stu2 = c2.newInstance();
-
-
利用有参构造
类对象.getDeclaredConstructor(参数1类对象,参数2类对象,..)
: 获取指定参数列表的有参构造器对象构造器对象.newInstance(实参列表)
: 利用有参构造器构建类的实例
//1. 获取有参构造器 Constructor<Student> con = c1.getDeclaredConstructor(String.class, int.class, double.class); //2. 构建实例 Student stu3 = con.newInstance("lisi", 21, 88.5);
优缺点
- 优点
- 打破封装
- 提高操作的扩展性
- 缺点:
- 打破封装
- 降低数据的安全性
- 书写
设计模式
是一种编码套路
单例模式
一个类只能创建一个实例
饿汉式
直接创建唯一实例
package com.by.entity;
/**
* 单例模式-饿汉式
*/
public class ClassA {
//static: 1. newClassA可以访问返回 2. 静态属性内存中只会存在一个
//private: 防止外界直接访问属性
private static ClassA ca = new ClassA();
//外界获取唯一实例的渠道
//static:使外界直接通过类名访问
public static ClassA newClassA(){
return ca;
}
//构造私有化-防止外界调用构造创建对象
private ClassA(){
}
}
缺点: 有可能浪费空间
懒汉式
在获取实例时创建唯一对象
package com.by.entity;
/**
* 单例模式-懒汉式
*/
public class ClassB {
//static: 1. newClassA可以访问返回 2. 静态属性内存中只会存在一个
//private: 防止外界直接访问属性
private static ClassB cb = null;
//外界获取唯一实例的渠道
//static:使外界直接通过类名访问
//synchronized: 同步方法 预防线程安全问题
public static synchronized ClassB newClassB(){
if (cb == null) {//当第一次获取时再进行实例化
cb = new ClassB();
}
return cb;
}
//构造私有化-防止外界调用构造创建对象
private ClassB(){
}
}
缺点: 线程效率慢
懒汉式-进阶版
在懒汉式的基础上,利用同步代码块结合二次校验提高执行效率
package com.by.entity;
/**
* 单例模式-懒汉式进阶版
*/
public class ClassC {
//static: 1. newClassA可以访问返回 2. 静态属性内存中只会存在一个
//private: 防止外界直接访问属性
private static ClassC cc = null;
//外界获取唯一实例的渠道
//static:使外界直接通过类名访问
public static ClassC newClassC(){
if (cc == null) {//二次校验: 决定是否需要开启互斥锁 t1:true t2:true
synchronized (ClassC.class) {//临界资源对象: 当前类的类对象
//对属性进行实例化
if (cc == null) {//当第一次获取时再进行实例化
cc = new ClassC();
}
}
}
return cc;
}
//构造私有化-防止外界调用构造创建对象
private ClassC(){
}
}
工厂模式
- 是一种底层技术,通常用于底层框架的编写
- 思路: 将数据的创建和维护交由工厂完成
案例
- 需求: 构建一个工厂类,获取学生对象
-
提供学生类
package com.by.entity; public class Student { private String name; private int age; private double score; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public double getScore() { return score; } public void setScore(double score) { this.score = score; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", score=" + score + '}'; } public Student() { } public Student(String name, int age, double score) {//string,int,double this.name = name; this.age = age; this.score = score; } }
-
书写配置文件
- 在项目下创建后缀名为
.properties
的配置文件 - 作用: 存放被管理类的全限定名
- 以
键=值
的形式存放数据 - 键值不可添加双引号、末尾不可添加分号、中间不可存在多个符号(如空格)
- 一行只能有一个键值对
StudentClassName=com.by.entity.Student
- 在项目下创建后缀名为
-
书写工厂类
package com.by.util; import com.by.entity.Student; import java.io.FileInputStream; import java.util.Properties; public class MyFactory { /** * 获取学生对象 */ public static Student getStudent(){ Student student = null; try ( //创建输入流 FileInputStream fis=new FileInputStream("factory.properties") ) { //将配置文件的内容加载到集合中 Properties p = new Properties(); p.load(fis); //获取全限定名 String className = p.getProperty("StudentClassName"); //获取类对象 Class c = Class.forName(className); //利用反射构建学生实例 student = (Student) c.newInstance(); } catch (Exception e) { System.out.println("未知异常!"); e.printStackTrace(); } return student; } }
-
测试
package com.by.test; import com.by.entity.Student; import com.by.util.MyFactory; public class Test5 { public static void main(String[] args) { //利用工厂获取学生实例对象 Student s1 = MyFactory.getStudent(); Student s2 = MyFactory.getStudent(); } }