2022-08-10 第八小组 学习笔记

发布于:2023-01-22 ⋅ 阅读:(5) ⋅ 点赞:(0) ⋅ 评论:(0)

目录

注解(Annotation)

Annotation可以用在什么地方呢?

 注解的作用

注解中也可以有方法

Annotation接口

Annotation可以为哪些程序元素设置元数据呢?

ElementType  枚举

RetentionPolicy 枚举

JAVA自带的注解--10个(4个注解在java.lang.annotation,6个注解在java.lang)

作用在代码上的注解

元注解

基本的元标签有

反射

得到class的三种方式

通过 Class 类获取成员变量、成员方法、接口、超类、构造方法等


注解(Annotation)

是JDK5.0开始引入的一种注释机制

@注解名的形式存在于代码中,Java中内置了一些注解,比如:@Override。当然也可以自定义注解。注解也可以有参数,例如@MyAnnotation(value = "菠萝吹雪")


Annotation可以用在什么地方呢?

类、接口、方法、变量、参数以及等之上。

注解可以设置存在于不同的生命周期中,例如SOURCE(源码中),CLASS(Class文件中,默认是此保留级别),RUNTIME(运行期中)。

举例:下面我们重写一个toString方法。

   @Override
    public String toString() {
        return super.toString();
    }

然后我们CTRL+左键,进入到Override的源码中,如图可以看到Override的注解,可以看到,是从jdk1.5开始的。

 注解的作用

1.作为一种辅助信息,对程序做出一些解释。

例如:@Override注解作用域方法上,表示此方法是重写了父类的方法。

2.可以被其他程序读取。例如:编辑器。

注解中也可以有方法

1.定义方法的格式:String name();

2.可以有默认值,也可以没有,如果没有默认值,在使用的时候必须填写对应的值,如果需要有默认值,使用default指定默认值。

3.如果想在使用的时候不指定具体名字,方法名写value


在Java整个注解体系中,有三个非常重要的主干类

Annotation接口

Annotation可以为哪些程序元素设置元数据呢?

Annotation提供了为元素设置元数据的方法:包括修饰类、构造器、方法、成员变量、参数、局部变量的声明。

元数据的信息被存储在Annotation的"name=value"中。

ElementType  枚举

用来指定注解的类型,意思是:我的注解要用在哪里?

RetentionPolicy 枚举

用来指定注解的策略,不同类型的策略指定的注解的作用域不同。

(1)SOURCE,注解仅存在于编译器处理期间,编译器处理完之后,这个注解就没用了

(2)CLASS,注解在class文件中依然有效

(3)RUNTTME,编译器是不起作用的,只有在运行期由JVM读取。

JAVA自带的注解--10个(4个注解在java.lang.annotation,6个注解在java.lang

作用在代码上的注解

@Override注解仅作用在方法上,被标识方法表示重写父类的方法,用这个注解可以避免方法名跟参数写错。

@Deprecated:意思是说此方法已过时,过时的原因就是有新的API的类替代了次方法。被划去的方法仍然是可以正常使用的,就是一个提示而已。

@SuppressWarnings:编辑器去忽略警告

public class Ch01 {

    @Deprecated
    @SuppressWarnings("all")
    public void info() {

    }

@SafeVarargs :Java 7开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。

@FunctionalInterfaceJava 8 开始支持,标识一个匿名函数或函数式接口。

@RepeatableJava 8 开始支持,标识某注解可以在同一个声明上使用多次。

元注解

专门给注解加的注解。可以理解为:元注解也是标签,但它是一种特殊的标签,作用和目的就是给其他普通标签进行解释说明。


基本的元标签有

@Documented:标记这个注解是否包含在用户文档中

@Target:这个注解可以修饰哪些信息

@Inherited(继承):如果一个类用上了@Inherited注解,那么其子类也会继承这个注解

@Retention:标识这个注解的作用域

反射

Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。


下面我们定义一个类----Person

本案例来自:Java 反射详解 - YSOcean - 博客园

package com.ys.reflex;
public class Person {
    //私有属性
    private String name = "Tom";
    //公有属性
    public int age = 18;
    //构造方法
    public Person() {
    }
    //私有方法
    private void say(){
        System.out.println("private say()...");
    }
    //公有方法
    public void work(){
        System.out.println("public work()...");
    }
}

得到class的三种方式

//1、通过对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object
//  类型的对象,而我不知道你具体是什么类,用这种方法
  Person p1 = new Person();
  Class c1 = p1.getClass();

//2、直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高
//  这说明任何一个类都有一个隐含的静态成员变量 class
  Class c2 = Person.class;

//3、通过 Class 对象的 forName() 静态方法来获取,用的最多,
//   但可能抛出 ClassNotFoundException 异常
  Class c3 = Class.forName("com.ys.reflex.Person");

通过 Class 类获取成员变量、成员方法、接口、超类、构造方法等

getName():获得类的完整名字。
getFields():获得类的public类型的属性。
getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
getMethods():获得类的public类型的方法。
getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
getMethod(String name, Class[ ] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
getConstructors():获得类的public类型的构造方法。
getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

演示

//获得类完整的名字
String className = c2.getName();
System.out.println(className);//输出com.ys.reflex.Person

//获得类的public类型的属性。
Field[] fields = c2.getFields();
for(Field field : fields){
   System.out.println(field.getName());//age
}

//获得类的所有属性。包括私有的
Field [] allFields = c2.getDeclaredFields();
for(Field field : allFields){
    System.out.println(field.getName());//name    age
}

//获得类的public类型的方法。这里包括 Object 类的一些方法
Method [] methods = c2.getMethods();
for(Method method : methods){
    System.out.println(method.getName());//work waid equls toString hashCode等
}

//获得类的所有方法。
Method [] allMethods = c2.getDeclaredMethods();
for(Method method : allMethods){
    System.out.println(method.getName());//work say
}

//获得指定的属性
Field f1 = c2.getField("age");
System.out.println(f1);
//获得指定的私有属性
Field f2 = c2.getDeclaredField("name");
//启用和禁用访问安全检查的开关,值为 true,则表示反射的对象在使用时应该取消 java 语言的访问检查;反之不取消
f2.setAccessible(true);
System.out.println(f2);

//创建这个类的一个对象
Object p2 =  c2.newInstance();
//将 p2 对象的  f2 属性赋值为 Bob,f2 属性即为 私有属性 name
f2.set(p2,"Bob");
//使用反射机制可以打破封装性,导致了java对象的属性不安全。
System.out.println(f2.get(p2)); //Bob

//获取构造方法
Constructor [] constructors = c2.getConstructors();
for(Constructor constructor : constructors){
    System.out.println(constructor.toString());//public com.ys.reflex.Person()
}

网站公告

欢迎关注微信公众号

今日签到

点亮在社区的每一天
签到