实例化对象: 通过类的构造方法实例化对象(正向)
获取Class : 通过实例化对象获取创建该对象的类(反向)
Object 类中 getClass() 返回一个Class类型的对象
Class : 类型
类: 现实事物的抽象
对象: 现实的具体事物(你所关注的事物对象)
一丶三种实例化对象
1丶通过构造方法实例化对象
2丶通过反射创建类的实例化对象
类的Class对象的newinstance()方法获取实例化对象(前提是类有无参数的构造方法)
类的Class对象获取构造方法的Constructor对象,通过Constructor的newInstance(…)实例化对象
3丶通过反序列化创建对象
getName() 获得全限定名
getsimpleName() 获得父类名
import java.util.Date;
public class TestReflect {
public static void mai1(String[] args) {
//Date
//java.util.Date API
Date date = new Date();
//类型
//class 关键字
//Class 类型
//Class toString()
//1丶一个类的实例化对象的getClass()获取
Class aClass = date.getClass();
System.out.println(aClass);//java.util.Date
//2丶类型名称class eg: Date.class
//如果date是Date类 返回 true 否则 false
System.out.println(date instanceof Date);
Class classz = Date.class;
System.out.println(classz);
//3丶Class.forName(类的全限定名)
//Class.forName
//java.util.Date => "java.util.Date"
//className => 类的全限定名 packageName.className
try {
Class classzz = Class.forName("java.util.Date");
System.out.println(classzz);
System.out.println("---------------");
//3 种方式
// 当前三个Class对象 都是描述 java.util.Date
System.out.println(aClass == classz);
System.out.println(classz == classzz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Class dateClass = Date.class;
try {
//object 是 java.util.Date
Object object = dateClass.newInstance();
Date date = (Date)object;
System.out.println(object);
System.out.println(object instanceof Date);
System.out.println(object.getClass());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
**二丶反射工厂模式**
public class TestFactory {
public static void main(String[] args) {
Fruit fruit = FruitFactory.getFruitInstance("com.changehyh.github.reflect.Orange");
fruit.eat();
}
}
interface Fruit {
void eat();
}
class Apple implements Fruit {
@Override
public void eat() {
System.out.println(“吃苹果”);
}
}
class Orange implements Fruit {
@Override
public void eat() {
System.out.println(“吃橘子”);
}
}
class FruitFactory {
private FruitFactory() {
}
public static Fruit getFruitInstance(String className) {
//new -> 具体类型耦合
try {
Class classz = Class.forName(className);
return (Fruit) classz.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
//
throw new RuntimeException(" Factory 生产不了 " + className);
}
}
反射调用
获取Class类的三种方式:
1丶一个类的实例化对象的getClass()获取
2丶类型名称.class eg: Date.class
3丶Class.forName(类的全限定名)
同一个类加载其中一个类的Class对象只有一个
取得父类信息
public class TestClass {
public static void main(String[] args) {
//1. new Test().getClass();
//2. Test.class
//3. Class.forName("com.bittech.reflect.Test")
Class cls = Test.class;
System.out.println("包名:" + cls.getPackage());
System.out.println("父类:" + cls.getSuperclass().getName());//类的全限名 包名.类名
System.out.println("父类:" + cls.getSuperclass().getSimpleName());//类名
System.out.println("接口:" );
//实例化
Class[] interfaces = cls.getInterfaces();
for (Class clsz:interfaces){
System.out.println(clsz.getName());
System.out.println(clsz.getSimpleName());
}
}
}
2丶反射调用构造
⼀个类中可以存在多个构造⽅法,如果要想取得类中构造的调用,就可以使用Class类中提供的两个方法:
1、取得指定参数类型的构造 getParameterTypes()
2、取得类中的所有构造 getConstructors()
Class类通过反射实例例化类对象的时候,只能够调用类中的无参构造。如果现在类中没有⽆参构造则⽆法使用Class类调用,只能够通过明确的构造调⽤实例化处理
class Test implements Fruit,Message{
public Test(Integer a,Integer b){
}
public Test(Integer a,String b){
}
public Test(Integer a){
}
public Test(){
}
}
取得指定参数类型的构造 getParameterTypes()
public static void main(String[] args) {
//Test1(int a, int b); => Test1(int, int) => Test1(int.class, int.class)
//Test1(int a, String b); => Test1(int,String)
//Test1(int a); => Test1(int)
Class clz = Test.class;
Constructor[] constructors = clz.getConstructors();
System.out.println("获取所有的构造方法");
for (Constructor constructor:constructors){
Class [] parameterCls= constructor.getParameterTypes();
String parameter = Arrays.toString(parameterCls);
System.out.println(
constructor.getName() + "("+parameter+")"
);
}
}
取得构造方法
public static void main(String[] args) {
System.out.println("获取指定的构造方法");
try {
/*
Constructor constructor = clz.getConstructor(Integer.class,String.class);
System.out.println(constructor);
//通过Constructor实例化对象
//new Test(...)
Object object = constructor.newInstance(20,"java");
System.out.println(object.getClass());
*/
Constructor constructor =clz.getConstructor(Integer.class,Integer.class);
System.out.println(constructor);
//通过Constructor实例化对象
//new Test(...)
Object object = constructor.newInstance(20,22);
System.out.println(object.getClass());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
反射调用类中属性
类中的所有属性一定在类对象实例化之后才会进行空间分配,所以此时如果要想调用类的属性,必须保证有实例化对象。通过反射的newInstance()可以直接取得实例化对象(Object类型);
1、 获取类中的全部属性:
2、获取指定属性
class Student extends Person{
private String school;
private String skill;
private LocalDateTime birthday;
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
public LocalDateTime getBirthday() {
return birthday;
}
public void setBirthday(LocalDateTime birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Student{" +
"school='" + school + '\'' +
", skill='" + skill + '\'' +
", birthday=" + birthday +
'}';
}
}
1丶获取类中全部属性
public static void main(String[] args) {
Class cls = Student.class;
//子类继承父类的所有结构,是否能否访问取决于访问修饰符
System.out.println("获取全部属性");
//Field[] fields = cls.getFields();//返回父类和子类的公开属性
Field[] fields = cls.getDeclaredFields();//返回子类的所以属性
for (Field field:fields){
System.out.println(field.getType() + " " +field.getName());
System.out.println(field);
}
}
2、获取指定属性
public static void main(String[] args) {
//自己
System.out.println("获取指定属性");
try {
Field skillField = cls.getDeclaredField("skill");
System.out.println(skillField);
//使用属性
Student student = new Student();
student.setSkill("Java,PHP,Python,JavaScript");
// student.getSkill()
//true 表示可以访问私有的属性
skillField.setAccessible(true);
//get 获取
Object skillValue = skillField.get(student);
System.out.println(skillValue);
//set 修改
skillField.set(student,"C++");
System.out.println(student);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
不加 skillField.setAccessible(true); 不能访问 private 的属性
true 表示可以访问私有的属性
**
ClassLoader类加载器
**
Class类描述的是整个类的信息,在Class类中提供的forName()⽅法,这个⽅法根据ClassPath配置的路径进行类的加载,如果说现在你的类的加载路径可能是网络、文件,这个时候就必须实现类加载器,也就是ClassLoader类的主要作⽤。
Bootstrap(启动类加载器):这个类加载器使用C++实现,是虚拟机⾃身的一部分;其他的类加载器都由Java语⾔言实现,独立于JVM外部并且都继承于java.lang.ClassLoader.BootStrap类加载器负责将存放于<Java_HOME>\lib目录中(或者被-Xbootclasspath参数指定路径中)能被虚拟机识别的(仅按照文件名识别,如rt.jar,名字不符合的类库即使放在lib目录中也不会被加载)类库加载到JVM内存中。启动类加载
器无法被Java程序直接引⽤。
ExtClassLoader(扩展类加载器):它负责加载<Java_HOME>\lib\ext目录中,或者被java.ext.dirs系统变量指定的路径中的类库。开发者可以直接使用扩展类加载器。
AppClassLoader(应用程序类加载器):负责加载用户类径(ClassPath)上指定的类库,如果应⽤程序中没有自定义自己的类加载器,则此加载器就是程序中默认的类加载器。
public class TestClassLoader {
public static void main(String[] args) {
Class memberCls = Member.class;
//获取ClassLoader
//AppClassLoader(应用程序类加载器)
System.out.println(memberCls.getClassLoader());
//ExtClassLoader(扩展类加载器)
System.out.println(memberCls.getClassLoader()
.getParent());
//null ->Bootstrap(启动类加载器) ClassLoader
System.out.println(memberCls.getClassLoader()
.getParent().getParent());
}
}
//1. com.changehyh.github.classloader
//2. com.changehyh.github.classloader.Member
//3. %classpath%/com/changehyh/github/classloader/Member.class
//4. Member.class对象
class Member{
}
双亲委派模型
上图加载器的关系就是双亲委派模型
双亲委派模型的工作流程是:如果⼀个类加载器收到了类加载请求,它⾸先不会自⼰己去尝试加载这个类,而是把这个请求委托给⽗类加载器去完成,每⼀个层次的类加载器都是如此。因此,所有的加载请求都应当传送到顶层的BootStrap加载器中,只有当⽗加载器反馈无法完成这个加载请求时(在自己搜索范围中没有找到此类),子加载器才会尝试⾃己去加载。
双亲委派模式对于保证Java程序的稳定运行很重要,Java类随着它的类加载器⼀一起具备了一种带有优先级的层次关系。
Object类在程序的各种类加载器环境中都是同⼀个类
import java.lang.reflect.Method;
public class TestObject {
public static void main(String[] args) {
Class cls = Object.class;
System.out.println(cls);
Method[] methods = cls.getDeclaredMethods();
for (Method method : methods){
System.out.println(method);
}
}
}
自定义类加载器:
用户自定义的类加载器
com.changehyh.github.classloader.Member1
public class Member1 {
@Override
public String toString() {
return "这是本地F盘的class文件";
}
}
MyClassLoader类继承ClassLoader类
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class MyClassLoader extends ClassLoader {
//用户自定义的类加载器
//com.changehyh.github.classloader.Member1
public Class loadClasses(String className){
byte[] byteCodeData = loadData(className);
//Class类 -> Class文件 -> ByteCode二进制流
return super.defineClass(className,byteCodeData,0,byteCodeData.length);
}
private byte[] loadData(String className) {
//Class文件的路径:F:\bit daima\20190520\out\production\20190520\com\changehyh\github\classloader\Member1.class
//Member1的类名:com.changehyh.github.classloader.Member1
//String classpath = "F:\\bit daima\\20190520\\out\\production\\20190520\\"classpath
// 环境变量配置,或者系统属性,命令行参数
String classpath = "F:\\bit daima\\20190520\\out\\production\\20190520\\";
String classFile = classpath + className.replace(".","\\\\") + ".class";
try (FileInputStream in = new FileInputStream(classFile);
ByteArrayOutputStream out = new ByteArrayOutputStream()
) {
byte[] buff = new byte[1024];
int len = -1;
while ((len = in.read(buff)) != -1){
out.write(buff, 0, len);
}
byte[] byteCodeData = out.toByteArray();
return byteCodeData;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public class TestMyClassLoader {
public static void main(String[] args) {
//Member1 -> AppClassLoader -> Class<Member1> a
//Member1 -> AppClassLoader -> Class<Member1> b
//Member1 -> AppClassLoader -> Class<Member1> c
//Member1 -> MyClassLoader -> Class<Member1> d
MyClassLoader myClassLoader = new MyClassLoader();
//Class
Class member1Cls1 = myClassLoader.loadClasses("com.changehyh.github.classloader.Member1");
//Class
Class member1Cls2 = Member1.class;
Class member1Cls3 = new Member1().getClass();
System.out.println(member1Cls1 == member1Cls2); //false 不同的类加载器
System.out.println(member1Cls2 == member1Cls3);//true 相同的类加载器
}
}
反射与代理设计模式
代理设计模式的核心本质在于:一个接口有两个⼦子类,⼀个负责真实业务,一个负责与真实业务有关的 所有辅助性操作。按照这样的原则,一个基础的代理设计模式如下:
接口如下:
package com.bittech.proxy;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* Author: secondriver
* Created: 2019/5/18
*/
public interface ISubject {
void eat();
}
//业务类
class RealSubject implements ISubject {
@Override
public void eat() {
System.out.println("饿了要吃饭");
}
}
class ProxySubject implements ISubject {
private ISubject subject;
public ProxySubject(ISubject subject) {
this.subject = subject;
}
public void prepare() {
System.out.println("饭前收拾食材");
}
public void afterEat() {
System.out.println("洗刷刷");
}
@Override
public void eat() {
this.prepare();
this.subject.eat(); // 核心吃
this.afterEat();
}
}
class Factory {
private Factory() {
}
public static <T> T getInstance(String realClassName) {
try {
Class cls = Class.forName(realClassName);
return (T) cls.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
throw new RuntimeException("factory create object failed by class " + realClassName);
}
public static <T> T getInstance(String proxyClassName, Object target) {//target 被代理对象 目标对象 代理对象的构造方法中
try {
Class cls = Class.forName(proxyClassName);
//限制:代理类只是实现代理接口
// Class[] proxyClassInterfaces = cls.getInterfaces();
// Class[] realClassInterfaces = target.getClass().getInterfaces();
Constructor constructor = cls.getConstructor(cls.getInterfaces()[0]);
return (T) constructor.newInstance(target);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
throw new RuntimeException("factory create object failed by class " + proxyClassName);
}
public static <T> T getProxyObject(String realClassName, String proxyClassName) {
T realObject = Factory.getInstance(realClassName);
T proxyObject = Factory.getInstance(proxyClassName, realObject);
return proxyObject;
}
}
真实业务:
package com.bittech.proxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* Author: secondriver
* Created: 2019/5/18
*/
public class RealSubject1 {
void eat() {
System.out.println("吃饭");
}
public static void main(String[] args) {
//真实业务对象 被代理对象
RealSubject1 realSubject1 = new RealSubject1();
//增强的业务对象
MethodInterceptor interceptor = new RealSubjectAdvance(realSubject1);
//代理对象
//enchaner生成代理对象
Enhancer enhancer = new Enhancer();
//代理类父类,处理逻辑
enhancer.setSuperclass(realSubject1.getClass());
enhancer.setCallback(interceptor);
RealSubject1 proxyObject = (RealSubject1) enhancer.create();
proxyObject.eat();
System.out.println(proxyObject.getClass());
}
}
//业务增强
class RealSubjectAdvance implements MethodInterceptor {
private final Object target;
RealSubjectAdvance(Object target) {
this.target = target;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("吃饭前,做饭");
Object returnValue = method.invoke(this.target, objects);
System.out.println("吃饭后,洗碗");
return returnValue;
}
}
业务辅助类
package com.bittech.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 该类:用于增强真实业务类对象的(被代理对象target)
* <p>
* Author: secondriver
* Created: 2019/5/18
*/
public class RealSubjectHandler implements InvocationHandler {
private final Object target;
public RealSubjectHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//invoke调用时
//method : 此时调用代理接口的method
//args : 此时调用代理接口的method方法传入的参数
System.out.println("做饭");//code ...
Object returnValue = method.invoke(this.target, args);
System.out.println("洗碗");
return returnValue;
}
}
测试类:
package com.bittech.proxy;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
/**
* Author: secondriver
* Created: 2019/5/18
*/
public class TestProxy {
public static void main(String[] args) {
/*
ISubject realObject= new RealSubject();
ISubject proxyObject = new ProxySubject(realObject);
proxyObject.eat();
*/
/*
ISubject realObject= Factory.getInstance("com.bittech.proxy.RealSubject");
ISubject proxyObject = Factory.getInstance("com.bittech.proxy.ProxySubject",realObject);
*/
/*
ISubject proxyObject = Factory.getProxyObject(
"com.bittech.proxy.RealSubject",
"com.bittech.proxy.ProxySubject"
);
proxyObject.eat();
*/
System.out.println("动态代理");
ISubject realSubject = new RealSubject();
InvocationHandler handler = new RealSubjectHandler(realSubject);
//代理对象
ISubject proxySubject = (ISubject) Proxy.newProxyInstance(
realSubject.getClass().getClassLoader(),
//动态生成的代理类的字节码需要类加载器,保证代理类和业务类在同一个类类加载器中
new Class[]{ISubject.class, CharSequence.class},// 动态生成的代理类实现的接口,Proxy.newProxyInstance返回的代理对象(Object)向下转型
handler//代理类动态生成的,无法动态生成业务增强,传入InvocationHandler接口的实例化对象
);
proxySubject.eat();
System.out.println("============");
System.out.println("类型:" + proxySubject.getClass());
System.out.println("接口:" + Arrays.toString(proxySubject.getClass().getInterfaces()));
System.out.println("父类:" + proxySubject.getClass().getSuperclass());
System.out.println("=============");
Constructor[] constructors = proxySubject.getClass().getConstructors();
for (Constructor c : constructors) {
System.out.println(c);
}
System.out.println("=============");
Method[] methods = proxySubject.getClass().getMethods();
for (Method method : methods) {
System.out.println(method);
}
//ByteCode
//1. .java -> .class
//2. .class ASM API
}
}