Java 反射进阶

2022-07-23  本文已影响0人  Tinyspot

1. 使用反射调用方法

// java.util.Properties#setProperty
public synchronized Object setProperty(String key, String value) {
  return put(key, value);
}

public static void main(String[] args) throws Exception {
    Properties properties = new Properties();
    // 用反射方式调用此方法 properties.setProperty("name", "boy");
    invokeMethod(properties, "setProperty", new Class[]{String.class, String.class}, "name", "boy");
    System.out.println(properties.toString());
}
/**
 * 反射调用方法
 * @param obj 对象
 * @param methodName 方法名
 * @param types 参数类型
 * @param args 参数的值
 * @return
 */
public static Object invokeMethod(Object obj, String methodName, Class<?>[] types, Object... args) throws Exception {
    Class<?> clazz = obj.getClass();
    // public Method getMethod(String name, Class<?>... parameterTypes) {}
    Method method = clazz.getMethod(methodName, types);
    // public Object invoke(Object obj, Object... args) {}
    return method.invoke(obj, args);
}

2. 工厂模式

工厂模式主要负责对象创建的问题
可通过反射进行工厂模式的设计,完成动态的对象创建

public static void main(String[] args) throws Exception {
    // Usb usb = UsbFactory.createUsb(Mouse.class);
    // usb.service();
    UsbFactory.service(Mouse.class);
}

public class UsbFactory {
    public static Usb createUsb(Class<?> clazz) {
        Usb usb = null;
        try {
            usb = (Usb) clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return usb;
    }

    public static void service(Class<?> clazz) {
        try {
            Usb usb = (Usb) clazz.newInstance();
            usb.service();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
public interface Usb {
    void service();
}
public class Mouse implements Usb {
    @Override
    public void service() {
        System.out.println("mouse running...");
    }
}

3. 泛型处理

Java通过泛型擦除,一但编译完成,所有和泛型有关的类型全部擦除

Class<User> userClass = User.class;
Method invoke = userClass.getMethod("invoke", Map.class, List.class);
Type[] genericParameterTypes = invoke.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
    // ParameterizedType 参数化类型
    if (genericParameterType instanceof ParameterizedType) {
        Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
        System.out.println(genericParameterType + "#" + Arrays.toString(actualTypeArguments));
    }
}

public void invoke(Map<String, Object> map, List<User> users) {
        System.out.println("invoke test");
    }

4. 注解处理

@Retention(RetentionPolicy.RUNTIME) 指定注解可以保留的域

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TypeValue {
    String value();
}

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValueInfo {
    String name();
    String type() default "";
}

@TypeValue("userInfo")
public class User {
    
    @ValueInfo(name = "age", type = "int")
    private Integer age;
    private String name;

    @ValueInfo(name = "test")
    public void test(String name) {
        System.out.println("test() running, name: " + name);
    }
}

获取方法上的注解

public static void main(String[] args) throws Exception {
    Class<?> clazz = User.class;
    Method method = clazz.getMethod("test", String.class);
    ValueInfo annotation = method.getAnnotation(ValueInfo.class);
    System.out.println(annotation.name() + ";" + annotation.type());
    // 调用方法
    User user = (User) clazz.newInstance();
    method.invoke(user, annotation.name());
}

获取属性上的注解

public static void main(String[] args) throws Exception {
    Class<?> clazz = User.class;
    System.out.println("类是否有TypeValue注解:" + clazz.isAnnotationPresent(TypeValue.class));

    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
        if (field.isAnnotationPresent(ValueInfo.class)) {
            ValueInfo annotation = field.getAnnotation(ValueInfo.class);
            System.out.println(field.getName() + "注解上的值为:" + annotation.name());
        }
    }
}

Field field = userClass.getDeclaredField("age");
FieldValue fieldValue = field.getAnnotation(FieldValue.class);
System.out.println(fieldValue.name() + "; " + fieldValue.type());

Annotation[] annotations = clazz.getAnnotations();
System.out.println(Arrays.toString(annotations));
上一篇下一篇

猜你喜欢

热点阅读