概述
傳統實現接口的方式需要implement
才行,通過註解實現一個接口可以減輕每次都要implement
的繁瑣。本文實現一個Demo來展示如何通過註解實現一個接口。
Code
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 利用反射與代理實現一個利用註解實現接口的功能,作爲展示,只支持函數接口,即接口中只有一個函數,且只支持一個接口。
*/
class Scratch {
public static void main(String[] args) throws Exception {
Lego lego = new Lego();
Playable playable = buildInterfaceClass(lego, Playable.class, Play.class);
playable.play();
}
/**
*
* @param object 有相應註解標記相應函數的類的對象
* @param interfaceClazz 待實現接口的Class
* @param annotationClazz 註解的Class
* @param <T> 接口類型
* @return 實現了接口的代理類對象
*/
@SuppressWarnings("unchecked")
public static <T> T buildInterfaceClass(Object object, Class<T> interfaceClazz, Class annotationClazz) {
return (T) Proxy.newProxyInstance(interfaceClazz.getClassLoader(), new Class[]{interfaceClazz}, new InterfaceHandler(object, annotationClazz));
}
/**
* 找出特定類上被特定註解標記的方法
* @param objectClass 類的Class
* @param annotationClass 註解的Class
* @return 被annotationClass標記的方法
* @throws Exception 沒有方法上面有annotationClass的註解
*/
public static Method getInterfaceMethod(Class<?> objectClass, Class<? extends Annotation> annotationClass) throws Exception {
Method[] declaredMethods = objectClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
Annotation[] declaredAnnotations = declaredMethod.getDeclaredAnnotations();
for (Annotation declaredAnnotation : declaredAnnotations) {
if (declaredAnnotation.annotationType().equals(annotationClass)) {
return declaredMethod;
}
}
}
throw new Exception("沒有含有 " + annotationClass.getName() + " 註解的方法");
}
/**
* 對代理類上相應的函數調用轉化爲被特定註解標記的函數調用
*/
private static class InterfaceHandler implements InvocationHandler {
private Object object;
private Class annotationClazz;
public InterfaceHandler(Object object, Class annotationClazz) {
this.object = object;
this.annotationClazz = annotationClazz;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().toLowerCase().endsWith(annotationClazz.getSimpleName().toLowerCase())) {
Method interfaceMethod = getInterfaceMethod(object.getClass(), annotationClazz);
return interfaceMethod.invoke(object, args);
}
throw new Exception("未實現函數");
}
}
}
/**
* 待實現的接口
*/
interface Playable {
void play();
}
/**
* 在方法上加上Play註解即可實現Playable中的Play方法
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Play {
}
/**
* 有註解標記函數的類,即我們希望通過註解實現接口的類
*/
class Lego {
@Play
void foo() {
System.out.println("I can play");
}
}