public static Class> forName(String className)
public final native Class> getClass();
Class<Person> p1 = Person.class;
System.out.println(p1.getName()); // 类的全路径
System.out.println(p1.getSimpleName()); // 类简称: Person
Class<?> p2 = Class.forName("com.example.interviewStudy.reflect.Person"); // forName方法中的参数需要是类的全路径
System.out.println(p1 == p2); // true, p1和p2指向同一个对象
Person person = new Person();
Class p3 = person.getClass();
System.out.println(p1 == p3); // true
Class p1 = Person.class;
Constructor<?>[] con1 = p1.getConstructors();
for (Constructor<?> c : con1) {
System.out.println(c.getName() +"<--->获取构造器参数总个数:" +c.getParameterCount());
}
System.out.println("获取所有构造器(包括私有的) ==>");
Constructor<?>[] con2 = p1.getDeclaredConstructors();
for (Constructor<?> c : con2) {
System.out.println(c.getName() +"<--->参数总个数:" +c.getParameterCount());
}
System.out.println("根据传入参数的类型 调用指定的构造器来创建对象 ==》");
Constructor publicPerson = p1.getConstructor(Long.class, String.class);
Person person1 = (Person) publicPerson.newInstance(10189L, "张三");
System.out.println(person1);
System.out.println("根据传入参数的类型 获取指定的 私有构造器 ==》");
Constructor<Person> privatePerson = p1.getDeclaredConstructor(String.class);
privatePerson.setAccessible(true); // 暴力反射,禁止检查访问权限,如果不禁止权限,则会报IllegalAccessException
// 调用无参构造器(将Person类中无参构造改为private修饰)
Person person2 = privatePerson.newInstance();
System.out.println(person2);
// 调用传入pname属性的构造器
Person person3 = privatePerson.newInstance("张小敬");
System.out.println(person3);
注意:如果不调用构造器对象的setAccessible,不禁止检查访问权限,就会报如下的
为测试获取Person类的私有属性,需要将Person的pname属性改为private修饰
Class p1 = Person.class;
// p1.getConstructors(): 只能获取public修饰的属性
// p1.getDeclaredFields(): 能获取所有的属性
Field[] fields = p1.getDeclaredFields();
// 遍历Person类中的成员变量
for (Field f : fields) {
System.out.println(f.getName() + "<--->" + f.getType());
}
// p1.getField(): 只能指定获取public修饰的成员变量
Field pname = p1.getDeclaredField("pname");
Person person = new Person();
// 给private修饰的成员变量赋值,需要禁止检查访问权限
pname.setAccessible(true);
pname.set(person,"朱重八");
System.out.println("person = " + person);
// 获取成员变量
// 从person 对象中获取pname
String name = (String) pname.get(person);
System.out.println(name);
Class p1 = Person.class;
Method[] methods = p1.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName() + "<-->" + method.getParameterCount() + "<-->访问修饰符:" + method.getModifiers());
}
Person person = new Person();
Method method1 = p1.getDeclaredMethod("printInfo", Long.class, String.class, Integer.class);
// 暴力反射
method1.setAccessible(true);
// 执行包含参数且有返回值的的成员方法,res1就是原本调用方法的返回值
Object res1 = method1.invoke(person, Long.valueOf(100897), "盛明兰", 26);
System.out.println(res1);
// 执行包含无参且没有返回值的成员方法,其原本方法的返回值就是null
Method method2 = p1.getDeclaredMethod("message");
method2.setAccessible(true);
Object res2 = method2.invoke(person);
System.out.println(res2);
实现一个简易版的持久化框架,对于任意一个对象,该框架都可以将对象的字段名和对应值,保存到txt格式的文本中
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
public class ObjectFrame {
public static void saveEntity(Object entity) throws IllegalAccessException, FileNotFoundException {
// append追加文本的形式将数据输出data.txt文本中
PrintStream printStream = new PrintStream(new FileOutputStream("D:\\data1.txt",true));
Class clazz = entity.getClass();
String simpleName = clazz.getSimpleName();
printStream.println("=========" + simpleName + "==========");
// 获取entity对象所有的成员变量
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
String dataKey = field.getName();
String dataValue = field.get(entity) + "";
printStream.println(dataKey + " = " + dataValue);
}
printStream.close();
}
}
public static void main(String[] args) throws FileNotFoundException, IllegalAccessException {
Person p1 = new Person(1009876L,"张小敬",28);
Person p2 = new Person(2091823L,"雷东宝",32);
Person p3 = new Person(2091823L,"宋运辉",26);
ObjectFrame.saveEntity(p1);
ObjectFrame.saveEntity(p2);
ObjectFrame.saveEntity(p3);
Teacher t1 = new Teacher(101L,"李知恩","语文");
Teacher t2 = new Teacher(104L,"高启强","数学");
ObjectFrame.saveEntity(t1);
ObjectFrame.saveEntity(t2);
}
此外,反射在实际项目中还可以实现日志输出管理、公共字段/属性的自动填充(createUser、createTime、updateUser、updateTime)、事务、权限控制等,这需要结合AOP来实现
在Spring框架中,用反射来实例化Bean对象,用反射实现对象的属性拷贝的BeanUtils.copyProperties()方法;使用反射来自定义注解;
注解被用错位置在编译期间就会报错
创建型模式
,提供了一种创建对象的最佳方式,是指仅在内存中只创建一次对象的设计模式,在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象单例模式的应用场景:HttpClient、Spring中的对象、打印日志的logger、数据库连接池对象
/***
* 懒汉模式
*/
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton(){ }
// 如果不加锁,则不能保证线程安全
// 锁的粒度较粗,同JDK1.0中的HashTable的设计,故HashTable不建议使用
public static synchronized LazySingleton getInstance(){
if (instance == null){
instance = new LazySingleton();
}
return instance;
}
}
public class HungrySingleton {
private static HungrySingleton instance = new HungrySingleton();
private HungrySingleton(){ }
public static HungrySingleton getInstance(){
return instance;
}
}
// DCL: Double Check Lock,双重锁校验
public class DCLSingleton {
// 基于volatile来保证可见性、有序性,禁止指令重排
private static volatile DCLSingleton instance;
private DCLSingleton() {
}
public static DCLSingleton getInstance() {
if (instance == null) { // 第一次检查
// 加锁保证线程安全
synchronized (DCLSingleton.class) {
if (instance == null) { // 再次检查防止同时进入synchronized
instance = new DCLSingleton();
}
}
}
return instance;
}
}
/**
* 静态内部类实现单例,线程安全
* StaticInnerSingleton类被装载了,instance不一定被实例化,因为SingletonHolder类没有被主动使用
* 当执行getInstance时,才会显示地装载SingletonHolder类,实例化instance
*/
public class StaticInnerSingleton {
private StaticInnerSingleton() {
}
private static class SingletonHolder {
private static final StaticInnerSingleton instance = new StaticInnerSingleton();
}
public static final StaticInnerSingleton getInstance() {
return SingletonHolder.instance;
}
}
public enum EnumSingleton {
INSTANCE;
// 执行业务代码
public void doSomeThing(){
System.out.println("执行业务逻辑....");
}
}
import java.util.concurrent.atomic.AtomicReference;
public class Singleton {
priavte static final AtomicReference<Singleton> casInstance = new AtomicReference<>();
public static final Singleton getInstance() {
for (; ; ) {
Singleton singleton = casInstance.get();
if (singleton != null) return singleton;
// 如果casInstance为null,则创建单例对象并返回
casInstance.compareAndSet(null,new Singleton());
return casInstance.get();
}
}
}