Java基础十四

27、注解

Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。
Java 语言中的类、方法、变量、参数和包等都可以被标注。和 Javadoc 不同,Java 标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容 。 当然它也支持自定义 Java 标注。
内置的注解:
Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。
作用在代码的注解是:
@Override: 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
@Deprecated: 标记过时方法。如果使用该方法,会报编译警告。
@SuppressWarnings 指示编译器去忽略注解中声明的警告。
作用在其他注解的注解(或者说 元注解)是:
@Retention 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
@Documented 标记这些注解是否包含在用户文档中。
@Target 标记这个注解应该是哪种 Java 成员。
@Inherited 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)

从 Java 7 开始,额外添加了 3 个注解:
@SafeVarargs Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
@FunctionalInterface Java 8 开始支持,标识一个匿名函数或函数式接口。
@Repeatable Java 8 开始支持,标识某注解可以在同一个声明上使用多次。

一、Annotation 架构

  • 每1个Annotation对象,都会有唯一的RetentionPolicy属性。
  • 对于每 1 个 Annotation 对象,可以有若干个 ElementType 属性。
  • Annotation 有许多实现类,包括:Deprecated, Documented, Inherited, Override 等等。Annotation 的每一个实现类,都 “和 1 个 RetentionPolicy 关联” 并且 " 和 1~n 个 ElementType 关联"。

二、Annotation 组成部分

java Annotation 的组成中,有 3 个非常重要的主干类。它们分别是:

package java.lang.annotation;
public interface Annotation {
    boolean equals(Object obj);
    int hashCode();
    String toString();
    Class<? extends Annotation> annotationType();
}
package java.lang.annotation;
public enum ElementType {
    TYPE,               /* 类、接口(包括注释类型)或枚举声明  */
    FIELD,              /* 字段声明(包括枚举常量)  */
    METHOD,             /* 方法声明  */
    PARAMETER,          /* 参数声明  */
    CONSTRUCTOR,        /* 构造方法声明  */
    LOCAL_VARIABLE,     /* 局部变量声明  */
    ANNOTATION_TYPE,    /* 注释类型声明  */
    PACKAGE             /* 包声明  */
}
package java.lang.annotation;
public enum RetentionPolicy {
    SOURCE,            /* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了  */
    CLASS,             /* 编译器将Annotation存储于类对应的.class文件中。默认行为  */
    RUNTIME            /* 编译器将Annotation存储于class文件中,并且可由JVM读入 */
}

三、java 自带的 Annotation

1、Annotation 通用定义

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

2、常用的 Annotation

  • @Deprecated: @Deprecated 所标注内容,不再被建议使用。
  • @Override: @Override 只能标注方法,表示该方法覆盖父类中的方法。
  • @Documented: @Documented 所标注内容,可以出现在javadoc中。
  • @Inherited: @Inherited只能被用来标注“Annotation类型”,它所标注的Annotation具有继承性。
  • @Retention: @Retention只能被用来标注“Annotation类型”,而且它被用来指定Annotation的RetentionPolicy属性。
  • @Target: @Target只能被用来标注“Annotation类型”,而且它被用来指定Annotation的ElementType属性。
  • @SuppressWarnings: @SuppressWarnings 所标注内容产生的警告,编译器会对这些警告保持静默。

四、Annotation 的作用

Annotation 是一个辅助类,它在 Junit、Struts、Spring 等工具框架中被广泛使用。
我们在编程中经常会使用到的 Annotation 作用有:
1、编译检查
Annotation 具有"让编译器进行编译检查的作用"。
@SuppressWarnings, @Deprecated 和 @Override 都具有编译检查作用。

public class OverrideTest {

    /**
     * toString() 在java.lang.Object中定义;
     * 因此,这里用 @Override 标注是对的。
     */
    @Override
    public String toString(){
        return "Override toString";
    }

    /**
     * getString() 没有在OverrideTest的任何父类中定义;
     * 但是,这里却用 @Override 标注,因此会产生编译错误!
     */
    @Override
    public String getString(){
        return "get toString";
    }
   
    public static void main(String[] args) {
    }
}

2、在反射中使用 Annotation
在反射的 Class, Method, Field 等函数中,有许多于 Annotation 相关的接口。
这也意味着,我们可以在反射中解析并使用 Annotation。

import java.lang.annotation.Annotation;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Inherited;
import java.lang.reflect.Method;

/**
 * Annotation在反射函数中的使用示例
 */
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
    String[] value() default "unknown";
}

/**
 * Person类。它会使用MyAnnotation注解。
 */
class Person {
   
    /**
     * empty()方法同时被 "@Deprecated" 和 "@MyAnnotation(value={"a","b"})"所标注
     * (01) @Deprecated,意味着empty()方法,不再被建议使用
     * (02) @MyAnnotation, 意味着empty() 方法对应的MyAnnotation的value值是默认值"unknown"
     */
    @MyAnnotation
    @Deprecated
    public void empty(){
        System.out.println("\nempty");
    }
   
    /**
     * sombody() 被 @MyAnnotation(value={"girl","boy"}) 所标注,
     * @MyAnnotation(value={"girl","boy"}), 意味着MyAnnotation的value值是{"girl","boy"}
     */
    @MyAnnotation(value={"girl","boy"})
    public void somebody(String name, int age){
        System.out.println("\nsomebody: "+name+", "+age);
    }
}

public class AnnotationTest {

    public static void main(String[] args) throws Exception {
       
        // 新建Person
        Person person = new Person();
        // 获取Person的Class实例
        Class<Person> c = Person.class;
        // 获取 somebody() 方法的Method实例
        Method mSomebody = c.getMethod("somebody", new Class[]{String.class, int.class});
        // 执行该方法
        mSomebody.invoke(person, new Object[]{"jiuling", 22});
        iteratorAnnotations(mSomebody);
       

        // 获取 somebody() 方法的Method实例
        Method mEmpty = c.getMethod("empty", new Class[]{});
        // 执行该方法
        mEmpty.invoke(person, new Object[]{});        
        iteratorAnnotations(mEmpty);
    }
   
    public static void iteratorAnnotations(Method method) {

        // 判断 somebody() 方法是否包含MyAnnotation注解
        if(method.isAnnotationPresent(MyAnnotation.class)){
            // 获取该方法的MyAnnotation注解实例
            MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
            // 获取 myAnnotation的值,并打印出来
            String[] values = myAnnotation.value();
            for (String str:values)
                System.out.printf(str+", ");
            System.out.println();
        }
       
        // 获取方法上的所有注解,并打印出来
        Annotation[] annotations = method.getAnnotations();
        for(Annotation annotation : annotations){
            System.out.println(annotation);
        }
    }
}

输出结果:

somebody: jiuling, 22
girl, boy, 
@com.skywang.annotation.MyAnnotation(value=[girl, boy])

empty
unknown, 
@com.skywang.annotation.MyAnnotation(value=[unknown])
@java.lang.Deprecated()

3、根据 Annotation 生成帮助文档
通过给 Annotation 注解加上 @Documented 标签,能使该 Annotation 标签出现在 javadoc 中。
4、能够帮忙查看查看代码
通过 @Override, @Deprecated 等,能很方便的了解程序的大致结构。也可以通过自定义 Annotation 来实现一些功能。

28、集合【Collection】

一、Collection

集合的结构图:
在这里插入图片描述
1、List【有序,可重复】

  • ArrayList
    优点: 底层数据结构是数组,查询快,增删慢。
    缺点: 线程不安全,效率高
  • Vector
    优点: 底层数据结构是数组,查询快,增删慢。
    缺点: 线程安全,效率低
  • LinkedList
    优点: 底层数据结构是链表,查询慢,增删快。
    缺点: 线程不安全,效率高

2、Set【无序,唯一】

  • HashSet

    • 底层数据结构是哈希表。(无序,唯一)
    • 怎么保证元素唯一性?
      1、实现hashCode()方法
      2、实现equals()方法
  • LinkedHashSet
    底层数据结构是链表和哈希表。(FIFO插入有序,唯一)
    1、由链表保证元素有序
    2、由哈希表保证元素唯一

  • TreeSet
    SortedSet是个接口,它里面的(只有TreeSet这一个实现可用)中的元素一定是有序的。

    底层数据结构是红黑树。(唯一,有序)
    1、如何保证元素排序的呢?
                自然排序
                比较器排序
    2、如何保证元素唯一性的呢?
          根据比较的返回值是否是0来决定

3、Queue

  • Queue接口与List、Set同一级别,都是继承了Collection接口。看图你会发现,LinkedList既可以实现Queue接口,也可以实现List接口.只不过呢, LinkedList实现了Queue接口。Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时,就完全只能访问Queue接口所定义的方法 了,而不能直接访问 LinkedList的非Queue的方法),以使得只有恰当的方法才可以使用。

注意事项:
List【不唯一】:

  • 线程是否安全:
    是:Vector
    否:ArrayList或者LinkedList
    如果知道是List,但是不知道是哪个List,就用ArrayList。
  • 查询多:ArrayList
    增删多:LinkedList

Set【唯一】:

  • 排序:
    是:TreeSet或LinkedHashSet
    否:HashSet
    如果知道是Set,但是不知道是哪个Set,就用HashSet。

二、Map

1、Map实现类的分类:

  • Hashtable
    无序的、方法是同步的、线程安全、效率较低、不允许null值、父类是Dictionary
  • HashMap
    无序的、方法不是同步的、线程不安全、效率较高、允许null值(key和value都允许)、父类是AbstractMap
  • LinkedHashMap
    无序的
  • TreeMap
    有序的

2、TreeSet、LinkedHashSet和HashSet 的区别:

  • TreeSet的主要功能用于排序
  • LinkedHashSet的主要功能用于保证FIFO即有序的集合(先进先出)
  • HashSet只是通用的存储数据的集合

相同点:

  • Duplicates elements: 因为三者都实现Set interface,所以三者都不包含duplicate elements
  • Thread safety: 三者都不是线程安全的,如果要使用线程安全可以Collections.synchronizedSet()

不同点:

  • Performance and Speed: HashSet插入数据最快,其次LinkHashSet,最慢的是TreeSet因为内部实现排序
  • Ordering: HashSet不保证有序,LinkHashSet保证FIFO即按插入顺序排序,TreeSet安装内部实现排序,也可以自定义排序规则
  • null:HashSet和LinkHashSet允许存在null数据,但是TreeSet中插入null数据时会报NullPointerException

代码比较:

  public static void main(String args[]) {
        HashSet<String> hashSet = new HashSet<>();
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
        TreeSet<String> treeSet = new TreeSet<>();
        for (String data : Arrays.asList("B", "E", "D", "C", "A")) {
            hashSet.add(data);
            linkedHashSet.add(data);
            treeSet.add(data);
        }
        //不保证有序
        System.out.println("Ordering in HashSet :" + hashSet);
        //FIFO保证安装插入顺序排序
        System.out.println("Order of element in LinkedHashSet :" + linkedHashSet);
        //内部实现排序
        System.out.println("Order of objects in TreeSet :" + treeSet);
    }

输出结果:

Ordering in HashSet :[A, B, C, D, E] (无顺序)
Order of element in LinkedHashSet :[B, E, D, C, A] (FIFO插入有序)
Order of objects in TreeSet :[A, B, C, D, E] (排序)

小结:

注解: 注解是很重要的一个部分!尤其是在后面的WEB、框架、以及中间件和微服务中运用的特别的多。可见它的地位有多么的重要了!当学习完注解以后,在未来的道路上会有特别多的收获!
集合: 集合是未来存储各种类型的一种方式,它比数组快,但是底层仍然是靠数组实现的!它的效率更加高!因此,要好好的学习集合!为以后的学习奠定良好的基础!

总结:

      这个世界是美好的,生活是多姿多彩的!今天是6月6号,数字很吉利!最近一直在想Java基础的知识点!大部分的知识点基本上已经快更新完了!还有六篇博客就更新结束了!正在想后面的六篇博客写一些什么文案给各位小伙伴!真的有些让人头疼!
      今天的博客就先写到这里!或者后面的六篇博客写一些以后的学习方向和一些个人的所见所闻!Java是一个大的生态体系!除了Java,还应该学习底层的C语言和数据结构、设计模式,还有后期的Redis缓存和消息中间件,网络中的Netty框架,以及微服务这些。只能说学无止境,需要多去学习,才能更好的进步!
      如果本篇博客对大家有帮助,希望大家能够点赞、关注!在此先谢过各位小伙伴了!
      最后,愿我们都能在各行各业中能够取得不同的成就,不负亲人、朋友、老师、长辈和国家的期望!能够用自身的所学知识为国家贡献出自己的一份力量!一起加油!
                                                                                                                       2021年6月6日夜

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值