Java基础回顾系列-第八天-高级编程之反射编程
认识反射机制
要想理解反射的原理,首先要了解什么是类型信息。Java让我们在运行时识别对象和类的信息,主要有2种方式:一种是传统的RTTI,它假定我们在编译时已经知道了所有的类型信息;另一种是反射机制,它允许我们在运行时发现和使用类的信息。
每个类都会产生一个对应的Class对象,也就是保存在.class文件。所有类都是在对其第一次使用时,动态加载到JVM的,当程序创建一个对类的静态成员的引用时,就会加载这个类。Class对象仅在需要的时候才会加载,static初始化是在类加载时进行的。
Class类对象的三种实例化模式
// 小写class表示是一个类类型,大写Class表示这个类的名称
public final class Class<T> extends Object implements Serializable, GenericDeclaration, Type, AnnotatedElement, TypeDescriptor.OfField<Class<?>>, Constable {
}
package javase.util;
public class JavaAPIDemo {
public static void main(String[] args) {
// 1、Object支持:类实例.getClass()
Person person = new Person();
Class<? extends Person> personClass = person.getClass();
System.out.println("personClass = " + personClass); // class javase.util.Person
String className = personClass.getName();
System.out.println("className = " + className); // javase.util.Person
// 2、JVM直接支持:类.class
Class<Person> personClass1 = Person.class;
System.out.println("personClass1 = " + personClass1); // class javase.util.Person
String className1 = personClass1.getName();
System.out.println("className2 = " + className1); // javase.util.Person
// 3、Class支持:Class.forName(全限类名)
try {
Class<?> aClass = Class.forName("javase.util.Person");
System.out.println("aClass = " + aClass); // class javase.util.Person
String className2 = aClass.getName();
System.out.println("className2 = " + className2); // javase.util.Person
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
// 普通类
class Person {
}
反射应用案例
反射实例化对象
package javase.util;
import java.lang.reflect.InvocationTargetException;
public class JavaAPIDemo {
public static void main(String[] args) {
// 反射实例化对象
// JDK1.9之前的实例化
try {
Person newInstance = Person.class.newInstance(); // 等价于new 对象();注:无参构造
System.out.println("newInstance = " + newInstance);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// JDK1.9之后的实例化
try {
Object newInstance = Class.forName("javase.util.Person").getDeclaredConstructor().newInstance();
System.out.println("newInstance = " + newInstance);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class Person {
public Person(){
System.out.println("无参构造方法");
}
@Override
public String toString() {
return "嘻嘻嘻";
}
}
反射与工厂设计模式
package javase.util;
import java.lang.reflect.InvocationTargetException;
/**
* 反射与工厂设计模式
*/
public class JavaAPIDemo {
public static void main(String[] args) {
// 获取服务接口
IService service = Factory.getInstance("javase.util.HouseService", IService.class);
service.service();
// 获取消息服务
IMessage message = Factory.getInstance("javase.util.NetMessage", IMessage.class);
message.send();
}
}
/**
* 工厂类
*/
class Factory {
/**
* 获取接口实例化对象
* @param className 接口子类名称
* @param clazz 描述的是一个接口的类型
* @param <T>
* @return
*/
public static <T> T getInstance(String className, Class<T> clazz) {
T instance = null;
try {
instance = (T)Class.forName(className).getDeclaredConstructor().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return instance;
}
}
/**
* 服务接口
*/
interface IService {
/**
* 服务处理
*/
public void service();
}
/**
* 住宿服务
*/
class HouseService implements IService {
@Override
public void service() {
System.out.println("【服务】为您的住宿提供服务。");
}
}
/**
* 消息接口
*/
interface IMessage {
/**
* 消息发送
*/
public void send();
}
/**
* 网络消息
*/
class NetMessage implements IMessage {
/**
* 消息发送
*/
public void send() {
System.out.println("【网络消息发送】北京乞丐月入万 很真实 ");
}
}
反射与单例设计模式
参考博文:不使用synchronized和lock,如何实现一个线程安全的单例?
懒汉式的单例线程安全问题:
package javase.util;
import java.lang.reflect.InvocationTargetException;
/**
* 单例线程安全
*/
public class JavaAPIDemo {
public static void main(String[] args) {
// 模拟多线程操作
for (int i = 0; i < 3; i++) {
new Thread(()->{
Singleton.getInstance();
}).start();
}
}
}
/**
* 单例对象
*/
class Singleton {
private static Singleton instance = null;
private Singleton() {
System.out.println("实例化操作");
}
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
线程安全的正确写法:
package javase.util;
import java.lang.reflect.InvocationTargetException;
/**
* 单例线程安全
*/
public class JavaAPIDemo {
public static void main(String[] args) {
// 模拟多线程操作
for (int i = 0; i < 3; i++) {
new Thread(()->{
Singleton.getInstance();
}).start();
}
}
}
/**
* 单例对象
*/
class Singleton {
private static Singleton instance = null;
private Singleton() {
System.out.println("实例化操作");
}
/**
* 同步安全处理:
* 方式一:public static synchronized Singleton getInstance() 影响效率
* 方式二:如下
* @return
*/
public static Singleton getInstance() {
if(instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
反射与类操作
反射获取类结构信息
package javase.util;
import java.io.Serializable;
/**
* 反射获取类结构信息
*/
public class JavaAPIDemo {
public static void main(String[] args) {
// 获取包名
String packageName = Person.class.getPackageName();
System.out.println("packageName = " + packageName);
// 获取父类
Class<? super Person> superclass = Person.class.getSuperclass();
String simpleName = superclass.getSimpleName();
System.out.println("simpleName = " + simpleName);
// 获取接口
Class<?>[] interfaces = Person.class.getInterfaces();
for (Class clazz : interfaces) {
String clazzName = clazz.getName();
System.out.println("clazzName = " + clazzName);
}
}
}
class Person extends Object implements Serializable, AutoCloseable {
@Override
public void close() throws Exception {
}
}
反射调用构造方法
package javase.util;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* 反射获取类结构信息
*/
public class JavaAPIDemo {
public static void main(String[] args) {
// 获取所有构造方法
Constructor<?>[] declaredConstructors = Person.class.getDeclaredConstructors();
for (Constructor constructor : declaredConstructors) {
System.out.println("constructor = " + constructor);
}
// 获取指定的构造方法
try {
Constructor<Person> declaredConstructor = Person.class.getDeclaredConstructor(String.class, int.class);
try {
Person person = declaredConstructor.newInstance("张三", 34);
System.out.println("person = " + person);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
class Person {
private String name;
private int age;
public Person(){}
public Person(String name){
this.name = name;
this.age = 0;
}
public Person(String name, int age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "姓名:"+this.name+"、年龄:"+this.age;
}
}
getConstructors()与getDeclaredConstructors区别
class Person {
private String name;
private int age;
// 构造函数1
public Person(){}
// 构造函数2
protected Person(String name){
this.name = name;
this.age = 0;
}
// 构造函数3
private Person(String name, int age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "姓名:"+this.name+"、年龄:"+this.age;
}
}
public static void main(String[] args) {
// getDeclaredConstructors()返回Class定义的所有构造函数,包括非public的
Constructor<?>[] declaredConstructors = Person.class.getDeclaredConstructors();
for (Constructor<?> constructor : declaredConstructors) {
System.out.println("constructor1 = " + constructor);
}
// getConstructors()只返回public修饰符的构造函数
Constructor<?>[] constructors = Person.class.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("constructor2 = " + constructor);
}
}
}
反射调用普通方法
package javase.util;
import java.io.Serializable;
import java.lang.reflect.*;
/**
* 反射获取类结构信息
*/
public class JavaAPIDemo {
public static void main(String[] args) {
// 获取全部方法
Method[] methods = Person.class.getMethods();
outMethodInfo(methods);
// 获取指定方法
try {
Method say = Person.class.getMethod("say");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
// 获取本类所有方法
Method[] declaredMethods = Person.class.getDeclaredMethods();
// 获取本类指定方法
try {
Method say2 = Person.class.getDeclaredMethod("say", String.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
// 方法调用,非常重要
try {
Class<?> aClass = Class.forName("javase.util.Person");
// 构造参数及实例化值
Object instance = aClass.getDeclaredConstructor(String.class).newInstance("张三");
// 方法调用
Method say = aClass.getMethod("say", String.class);
Object sayInvoke = say.invoke(instance, "lisa");
System.out.println("sayInvoke = " + sayInvoke);
// 方法调用
Method getName = aClass.getMethod("getName");
Object getNameInvoke = getName.invoke(instance);
System.out.println("getNameInvoke = " + getNameInvoke);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 输出方法
*
* @param methods
*/
public static void outMethodInfo(Method... methods) {
for (Method method : methods) {
// 获取修饰符
int modifiers = method.getModifiers();
String modifier = Modifier.toString(modifiers);
// 获取返回值类型
String returnType = method.getReturnType().getName();
// 方法名
String name = method.getName();
// 参数个数
int parameterCount = method.getParameterCount();
Class<?>[] parameterTypes = method.getParameterTypes();
String parameterTypeName = "";
for (Class parameterType : parameterTypes) {
parameterTypeName += parameterType.getName() + "、";
}
System.out.println("修饰符:" + modifier + "、返回类型:" + returnType + "、方法名:" + name + "、参数个数:" + parameterCount + "、参数类型:" + parameterTypeName);
}
}
}
class Person {
private String name;
private int age;
public Person() {
}
public Person(String name) {
this.name = name;
this.age = 0;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void say() {
}
public void say(String name) {
System.out.println(this.name + "对" + name + ":说");
}
@Override
public String toString() {
return "姓名:" + this.name + "、年龄:" + this.age;
}
public String getName(){
return "姓名:" + this.name;
}
}
反射调用成员
package javase.util;
import java.io.Serializable;
import java.lang.reflect.*;
/**
* 反射获取类结构信息
*/
public class JavaAPIDemo {
public static void main(String[] args) {
try {
Class<?> person = Class.forName("javase.util.Person");
// 获取本类全部成员
Field[] declaredFields = person.getDeclaredFields();
// 获取本类指定成员
Field name = person.getDeclaredField("name");
System.out.println("name.getName() = " + name.getName());
System.out.println("name.getType().getName() = " + name.getType().getName());
System.out.println("name.getType().getSimpleName() = " + name.getType().getSimpleName());
// 获取父类全部成员
Field[] fields = person.getFields();
// 获取父类指定成员
// Field age = person.getField("age");
Object instance = person.getDeclaredConstructor().newInstance();
// 出错:class javase.util.JavaAPIDemo cannot access a member of class javase.util.Person with modifiers "private"
// 解除字段封装.
name.setAccessible(true);
// 设置成员值
name.set(instance, "张三");
// 获取成员值
Object nameValue = name.get(instance);
System.out.println("nameValue = " + nameValue);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Person {
private String name;
private int age;
public Person() {
}
public Person(String name) {
this.name = name;
this.age = 0;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void say() {
}
public void say(String name) {
System.out.println(this.name + "对" + name + ":说");
}
@Override
public String toString() {
return "姓名:" + this.name + "、年龄:" + this.age;
}
public String getName(){
return "姓名:" + this.name;
}
}
Unfafe工具类
参考博文:Java中Unsafe类详解
package javase.util;
import sun.misc.Unsafe;
import java.io.Serializable;
import java.lang.reflect.*;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
Field field = Unsafe.class.getDeclaredField("theUnsafe") ; // 获取成员
field.setAccessible(true); // 解除封装
Unsafe unsafeObject = (Unsafe) field.get(null) ; // 原本的Field需要接收实例化对象,但是Unsafe不需要
Singleton instance = (Singleton) unsafeObject.allocateInstance(Singleton.class) ; // 获取对象,不受JVM控制
instance.print();// 调用类中的方法
}
}
class Singleton {
private Singleton() {
System.out.println("****** Singleton类的构造方法 ******");
}
public void print() {
System.out.println("www.mldn.cn");
}
}
反射与简单Java类
简单一:
package cn.mldn.demo;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
String value = "empno:7369|ename:Smith|job:Clerk|salary:750.00|hiredate:1989-10-10|" +
"dept.dname:财务部|dept.company.name:MLDN" ;
Emp emp = ClassInstanceFactory.create(Emp.class, value) ;
System.out.println("雇员编号:" + emp.getEmpno() + "姓名:" + emp.getEname() + "、职位:" + emp.getJob() + "、基本工资:"
+ emp.getSalary() + "、雇佣日期:" + emp.getHiredate());
System.out.println(emp.getDept().getDname());
System.out.println(emp.getDept().getCompany().getName());
}
}
class ClassInstanceFactory {
private ClassInstanceFactory() {}
/**
* 实例化对象的创建方法,该对象可以根据传入的字符串结构“属性:内容|属性:内容”
* @param clazz 要进行反射实例化的Class类对象,有Class就可以反射实例化对象
* @param value 要设置给对象的属性内容
* @return 一个已经配置好属性内容的Java类对象
*/
public static <T> T create(Class<?> clazz,String value) {
try { // 如果要想采用反射进行简单Java类对象属性设置的时候,类中必须要有无参构造
Object obj = clazz.getDeclaredConstructor().newInstance() ;
BeanUtils.setValue(obj, value); // 通过反射设置属性
return (T) obj ; // 返回对象
} catch (Exception e) {
e.printStackTrace(); // 如果此时真的出现了错误,本质上抛出异常也没用
return null ;
}
}
}
class StringUtils {
public static String initcap(String str) {
if (str == null || "".equals(str)) {
return str ;
}
if (str.length() == 1) {
return str.toUpperCase() ;
} else {
return str.substring(0,1).toUpperCase() + str.substring(1) ;
}
}
}
class BeanUtils { // 进行Bean处理的类
private BeanUtils() {}
/**
* 实现指定对象的属性设置
* @param obj 要进行反射操作的实例化对象
* @param value 包含有指定内容的字符串,格式“属性:内容|属性:内容”
*/
public static void setValue(Object obj,String value) {
String results [] = value.split("\\|") ; // 按照“|”进行每一组属性的拆分
for (int x = 0 ; x < results.length ; x ++) { // 循环设置属性内容
// attval[0]保存的是属性名称、attval[1]保存的是属性内容
String attval [] = results[x].split(":") ; // 获取“属性名称”与内容;
try {
if (attval[0].contains(".")) { // 多级配置
String temp [] = attval[0].split("\\.") ;
Object currentObject = obj ;
// 最后一位肯定是指定类中的属性名称,所以不在本次实例化处理的范畴之内
for (int y = 0 ; y < temp.length - 1 ; y ++) { // 实例化
// 调用相应的getter方法,如果getter方法返回了null表示该对象未实例化
Method getMethod = currentObject.getClass().getDeclaredMethod("get" + StringUtils.initcap(temp[y])) ;
Object tempObject = getMethod.invoke(currentObject) ;
if (tempObject == null) { // 该对象现在并没有实例化
Field field = currentObject.getClass().getDeclaredField(temp[y]) ; // 获取属性类型
Method method = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[y]), field.getType()) ;
Object newObject = field.getType().getDeclaredConstructor().newInstance() ;
method.invoke(currentObject, newObject) ;
currentObject = newObject ;
} else {
currentObject = tempObject ;
}
}
// 进行属性内容的设置
Field field = currentObject.getClass().getDeclaredField(temp[temp.length - 1]) ; // 获取成员
Method setMethod = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[temp.length - 1]), field.getType()) ;
Object convertValue = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]) ;
setMethod.invoke(currentObject, convertValue) ; // 调用setter方法设置内容
} else {
Field field = obj.getClass().getDeclaredField(attval[0]) ; // 获取成员
Method setMethod = obj.getClass().getDeclaredMethod("set" + StringUtils.initcap(attval[0]), field.getType()) ;
Object convertValue = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]) ;
setMethod.invoke(obj, convertValue) ; // 调用setter方法设置内容
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 实现属性类型转换处理
* @param type 属性类型,通过Field获取的
* @param value 属性的内容,传入的都是字符串,需要将其变为指定类型
* @return 转换后的数据
*/
private static Object convertAttributeValue(String type,String value) {
if ("long".equals(type) || "java.lang.Long".equals(type)) { // 长整型
return Long.parseLong(value) ;
} else if ("int".equals(type) || "java.lang.int".equals(type)) {
return Integer.parseInt(value) ;
} else if ("double".equals(type) || "java.lang.double".equals(type)) {
return Double.parseDouble(value) ;
} else if ("java.util.Date".equals(type)) {
SimpleDateFormat sdf = null ;
if (value.matches("\\d{4}-\\d{2}-\\d{2}")) { // 日期类型
sdf = new SimpleDateFormat("yyyy-MM-dd") ;
} else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") ;
} else {
return new Date() ; // 当前日期
}
try {
return sdf.parse(value) ;
} catch (ParseException e) {
return new Date() ; // 当前日期
}
} else {
return value ;
}
}
}
class Company {
private String name ;
private Date createdate ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreatedate() {
return createdate;
}
public void setCreatedate(Date createdate) {
this.createdate = createdate;
}
}
class Dept {
private String dname ;
private String loc ;
private Company company ;
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
}
class Emp {
private long empno ;
private String ename ;
private String job ;
private double salary ;
private Date hiredate ;
private Dept dept ;
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setJob(String job) {
this.job = job;
}
public String getEname() {
return ename;
}
public String getJob() {
return job;
}
public long getEmpno() {
return empno;
}
public void setEmpno(long empno) {
this.empno = empno;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Date getHiredate() {
return hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
}
二:
参考李兴华老师的视频:内容多,不继续贴出。
ClassLoader类加载器
类加载器介绍
类加载器是一个用来加载类文件的类。Java源代码通过javac编译器编译成类文件。然后JVM来执行类文件中的字节码来执行程序。类加载器负责加载文件系统、网络或其他来源的类文件。有三种默认使用的类加载器:Bootstrap类加载器、Extension类加载器和System类加载器(或者叫作Application类加载器)。正确理解类加载器能够帮你解决NoClassDefFoundError和java.lang.ClassNotFoundException,因为它们和类的加载相关。
- 委托机制是指将加载一个类的请求交给父类加载器,如果这个父类加载器不能够找到或者加载这个类,那么再加载它。
- 可见性的原理是子类的加载器可以看见所有的父类加载器加载的类,而父类加载器看不到子类加载器加载的类。
- 单一性原理是指仅加载一个类一次,这是由委托机制确保子类加载器不会再次加载父类加载器加载过的类。
参考博文:
https://www.cnblogs.com/sunniest/p/4574080.html
ClassLoader介绍
https://www.cnblogs.com/sunniest/p/4574080.html
自定义ClassLoader处理类
public class MyClassLoader extends ClassLoader{
private String rootPath;
public MyClassLoader(String rootPath){
this.rootPath = rootPath;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
//check if the class have been loaded
Class<?> c = findLoadedClass(name);
if(c!=null){
return c;
}
//load the class
byte[] classData = getClassData(name);
if(classData==null){
throw new ClassNotFoundException();
}
else{
c = defineClass(name,classData, 0, classData.length);
return c;
}
}
private byte[] getClassData(String className){
String path = rootPath+"/"+className.replace('.', '/')+".class";
InputStream is = null;
ByteArrayOutputStream bos = null;
try {
is = new FileInputStream(path);
bos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int temp = 0;
while((temp = is.read(buffer))!=-1){
bos.write(buffer,0,temp);
}
return bos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
is.close();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
反射与代理设计模式
参考博文:Java的三种代理模式
注:该博文写的非常清晰明了。
静态代理
动态代理
Cglib代理
反射与Annotation
参考博文:Java基础加强总结(一)——注解(Annotation)
获取Annotation信息
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
{ // 获取接口上的Annotation信息
Annotation annotations [] = IMessage.class.getAnnotations() ; // 获取接口上的全部Annotation
for (Annotation temp : annotations) {
System.out.println(temp);
}
}
System.out.println("-----------------------------------");
{ // 获取MessageImpl子类上的Annotation
Annotation annotations [] = MessageImpl.class.getAnnotations() ; // 获取接口上的全部Annotation
for (Annotation temp : annotations) {
System.out.println(temp);
}
}
System.out.println("-----------------------------------");
{ // 获取MessageImpl.toString()方法上的Annotation
Method method = MessageImpl.class.getDeclaredMethod("send", String.class) ;
Annotation annotations [] = method.getAnnotations() ; // 获取接口上的全部Annotation
for (Annotation temp : annotations) {
System.out.println(temp);
}
}
}
}
@FunctionalInterface
@Deprecated(since="1.0")
interface IMessage { // 有两个Annotation
public void send(String msg) ;
}
@SuppressWarnings("serial") // 无法在程序执行的时候获取
class MessageImpl implements IMessage, Serializable {
@Override // 无法在程序执行的时候获取
public void send(String msg) {
System.out.println("【消息发送】" + msg);
}
}
自定义Annotation
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
Method method = Message.class.getMethod("send", String.class) ; // 获取指定方法
DefaultAnnotation anno = method.getAnnotation(DefaultAnnotation.class) ; // 获取指定的Annotation
String msg = anno.title() + "(" + anno.url() + ")"; // 消息内容
method.invoke(Message.class.getDeclaredConstructor().newInstance(), msg) ;
}
}
@Retention(RetentionPolicy.RUNTIME) // 定义Annotation的运行策略
@interface DefaultAnnotation { // 自定义的Annotation
public String title() ; // 获取数据
public String url() default "www.mldn.cn" ; // 获取数据,默认值
}
class Message {
@DefaultAnnotation(title="MLDN")
public void send(String msg) {
System.out.println("【消息发送】" + msg);
}
}
Annotation与工厂设计模式结合案例
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
MessageService messageService = new MessageService() ;
messageService.send("www.mldn.cn");
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface UseMessage {
public Class<?> clazz() ;
}
@UseMessage(clazz=NetMessageImpl.class) // 利用Annotation实现了类的使用
class MessageService {
private IMessage message ;
public MessageService() {
UseMessage use = MessageService.class.getAnnotation(UseMessage.class) ;
this.message = (IMessage) Factory.getInstance(use.clazz()) ; // 直接通过Annotation获取
}
public void send(String msg) {
this.message.send(msg);
}
}
class Factory {
private Factory() {}
public static <T> T getInstance(Class<T> clazz) { // 直接返回一个实例化对象
try {
return (T) new MessageProxy().bind(clazz.getDeclaredConstructor().newInstance()) ;
} catch (Exception e) {
e.printStackTrace();
return null ;
}
}
}
class MessageProxy implements InvocationHandler {
private Object target ;
public Object bind(Object target) {
this.target = target ;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this) ;
}
public boolean connect() {
System.out.println("〖代理操作〗进行消息发送通道的连接。");
return true ;
}
public void close() {
System.out.println("〖代理操作〗关闭连接通道。");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (this.connect()) {
return method.invoke(this.target, args);
} else {
throw new Exception("【ERROR】消息无法进行发送!");
}
} finally {
this.close();
}
}
}
interface IMessage {
public void send(String msg) ;
}
class MessageImpl implements IMessage {
@Override
public void send(String msg) {
System.out.println("【消息发送】" + msg);
}
}
class NetMessageImpl implements IMessage {
@Override
public void send(String msg) {
System.out.println("【网络消息发送】" + msg);
}
}