Java速通 Day5 – 反射和注解

/ 0评 / 0

前两天都有点高强度了,所以这个隔了好一段时间缓一缓,今天写的也比较短,另外我本身有自己的工作,所以都是业余时间学习,所以更新笔记时间就更加不确定了,并不是全天都在学这个东西.写的比较菜比较片面,也希望大佬们温柔对待.

Java认为一切都是对象,每个都想都能归到某个类,所以,我们也可以获得这个对象对应的类.

public class basic {
    public static void main(String[] args) {
        Class classFromClass = Fruit.class;
        System.out.println(classFromClass.getName());

        Fruit fruit1 = new Fruit("苹果","red", 10.0,10.0);
        Class classFromFruit1 = fruit1.getClass();
        System.out.println(classFromFruit1.getName());
    }
}

输出结果

com.world.hello.Fruit
com.world.hello.Fruit

Class类也有一些常见的方法.

可以利用反射技术操作私有属性,这个操作并不使用对象的setXXX方法,即哪怕setXXX是私有或者根本没实现,都可以操作.

    public static void main(String[] args) {
        Fruit fruit = new Fruit("苹果","red", 10.0,10.0);
        try{
            Class clazz = fruit.getClass();
            Field price = clazz.getDeclaredField("price");
            // 看看是不是成功获得了!如果不成功就到异常不往下了.
            try{
                price.setAccessible(true);
                price.set(fruit, 50.0);
                System.out.println(fruit.getPrice());
            }catch(IllegalAccessError | IllegalAccessException e){
                e.printStackTrace();
            }
        }catch (NoSuchFieldException | SecurityException e){
            e.printStackTrace();
        }
    }

首先获得了这个类的Class对象,然后设置price这个Field不为private,然后通过Filed的set方法就可以修改他,上面代码执行后就会显示苹果价格是50.0.

对于私有方法也可以使用类似的方法.

    public static void main(String[] args) {
        Fruit fruit = new Fruit("苹果","red", 10.0,10.0);
        try{
            Class clazz = fruit.getClass();
            Method method = clazz.getDeclaredMethod("setPrice",Double.class);
            // 看看是不是成功获得了!如果不成功就到异常不往下了.
            try{
                method.setAccessible(true);
                method.invoke(fruit,50.0);
                System.out.println(fruit.getPrice());
            }catch(IllegalAccessError | IllegalAccessException | InvocationTargetException e){
                e.printStackTrace();
            }
        }catch (NoSuchMethodException | SecurityException e){
            e.printStackTrace();
        }
    }

不过由于Class能包裹的实在太多了,所以还要按照泛型一样给他修饰才算比较科学.

Class<? extends Fruit> clazz = fruit.getClass();

我们一直写代码中,IDEA偶尔会给我们添加一些特殊的字,比如@Override,这些不是注释,是注解,注解是给开发过程/运行过程检查使用的.前面说的Override就是代表此处从写了父类的方法,有些方法我们写的时候就提示废弃了,也是被注解了.

我们给一个不使用的函数添加一个注解,抑制未使用警告.

@SuppressWarnings("unused")
public static void notUsed(){
System.out.println("Hello World");
}

这样在IDEA就不报告警告了.

这些注解也是人规定的,我们随便打开Documented这个注解,发现他内容是这样的.

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

其中@Documented这个注解一旦存在,会被javadoc提取成文档,@Target表明注解的类型,可以是TYPE(类,接口,枚举),FIELD,METHOD(方法但不含构造方法),PARAMETER(方法的参数),CONSTRUCTOR(构造方法),LOCAL_VARIABLE(局部变量),ANNOTATION_TYPE(注解类型),PACKAGE(包),@Retention注明这个注解保留策略,SOURCE代表整个注解只在编码阶段保留,CLASS表示保留至CLASS文件,RUNTIME表示运行时依然能检测到他.

通过反射机制的可以知道有没有包含某个注解,注解也可以自行添加,比如这一句检查一下我刚提取的method有没有包含Documented的注解,自己写的注解也可以用,并不是只有系统内置注解.

method.isAnnotationPresent(Documented.class);

到这里,Java的基础知识应该就建立了,后面开始搞各种现成的轮子,至于自己做轮子,那完全就是看自己具体能力了.

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注