Java泛型与注解全面分析讲解

目录
  • 1.什么是泛型
  • 2.为何使用泛型
    • 2.1.如何定义泛型
    • 2.2.通配符
    • 2.3.受限泛型
    • 2.4.泛型接口
    • 2.5.泛型方法
  • 3.java高级--注解
    • 3.1.预定义注解
    • 3.2.自定义注解(初级)
    • 3.3.元注解
    • 3.4.自定义注解(高级)

1.什么是泛型

其实我们在使用集合时就用过泛型List<T> 创建一个List对象List<Student> list=new ArrayList();<T>它就是泛型。

所谓的泛型就是在类定义时,不为类中属性和方法指定数据类型,而是在类对象创建时为其指定相应的数据类型。

2.为何使用泛型

例子: 要求定义一个Point点类,该类中属性有x坐标和y坐标。

要求: x和y的值可以都是整数类型。

​ x和y的值可以都是小数类型。

​ x和y的值可以都是字符串类型。

如何定义该类呢? 如何确定属性的类型。----可以想到使用Object类型

如果我们为坐标一个赋值整数,一个赋值为字符串,这时不会报错 ,

但是它违背了我们设计的要求,这就是我们提到的数据类型安全问题。如何解决数据类型安全问题?可以使用泛型来解决,使用泛型就保证了数据类型安全问题 。

2.1.如何定义泛型

泛型可以定义在类上,接口上,方法上。 泛型类,泛型接口以及泛型方法。

泛型可以解决数据类型的安全性问题,其主要原理是在类声明时通过一个标识表示类中某个属性的数据类型或者是某个方法的返回值及参数类型。这样在类声明或者实例化时只要指定好需要的类型即可。

格式:

public class 类名<泛型标志,泛型标志....>{

//类成员

}

代码展示:

//T标志可以任意起名-----若此处有多个标志时,使用时必须为每个泛型指定数据类型
public class Student<T> {
    private T name;
    private T age;
    public void show(){
        System.out.println("name:"+name+"age:"+age);
    }
    public Student() {
    }
    public Student(T name, T age) {
        this.name = name;
        this.age = age;
    }
    public T getName() {
        return name;
    }
    public void setName(T name) {
        this.name = name;
    }
    public T getAge() {
        return age;
    }
    public void setAge(T age) {
        this.age = age;
    }
}

测试类:

public class StudentTest {
    public static void main(String[] args) {
        Student<Integer> stu=new Student<Integer>(33,44);
        stu.show();
        //若指定泛型类型默认为Object
        Student<String> stu1=new Student<>("张三","22");
        stu1.show();
        Student stu2=new Student("李四","55");
        String age = (String) stu2.getAge();//若想使用真正的类型接受,那么必须进行强转
        System.out.println(age);
    }
}

2.2.通配符

在开发中对象的引用传递是最常见的,但是如果在泛型类的操作中,在进行引用传递时泛型类型必须匹配才可以传递,否则是无法传递的。如果想传递,可以定义泛型为?通配符。

代码展示:

public class Test04 {
    public static void main(String[] args) {
            Info<Integer> i=new Info<>();
            i.setVar(25);
            fun(i);
            Info<String> i2=new Info<>();
            i2.setVar("张三");
            fun(i2); //如果下面不是使用通配符?则会报错  原因是如果为泛型类型:不但要求数据类型相同之外还要求泛型类型也匹配。
           Info<Double> i3=new Info<>();
           i3.setVar(25.5);
           fun(i3);
            //能不能设置泛型类型可以接受任意的类型呢? 我们可以使用同配置?
    }
    public static void fun(Info<?> info){
         info.show();
    }
}
//T标志可以任意起名.----> 那么在创建对象时,必须为每个泛型指定数据类型。
class Info<T>{
    private T var;
    public void show(){
        System.out.println("var========"+var);
    }
    public T getVar() {
        return var;
    }
    public void setVar(T var) {
        this.var = var;
    }
}

2.3.受限泛型

在引用传递中,在泛型操作中也可以设置一个泛型对象的范围上限和范围下限。范围上限使用extends关键字声明,表示参数化的类型可能是所指定的类型或者是此类型的子类,而范围下限使用super进行声明,表示参数化的类型可能是所指定的类型或者此类型的父类型。

语法:

[设置上限]

声明对象: 类名称<? extends 类> 对象名称;

定义类: [访问权限] 类名称<泛型标识 extends 类>{}

[设置下限]

声明对象: 类名称<? super 类> 对象名称;

定义类: [访问权限] 类名称<泛型标识 super 类>{}

代码展示:

public class ShangXiaXianTest {
    public static void main(String[] args) {
        Info<Number> i=new Info<>();
         fun2(i);
         Info<Object> i3=new Info<>();
         fun2(i3);
         Info<Integer> i4=new Info<>();
         fun2(i4);
    }
    //传递的参数泛型类型必须为Number的父类或者Number类型  下限
    public static void fun2(Info<? super Number> info){
        info.show();
    }
    //传递的参数泛型类型必须为Number的子类(注意String不是Number的子类)或者Number类型   上限
    public static void fun3(Info<? extends Number> info){
        info.show();
    }
    public static void fun(Info<?> info){
        info.show();
    }
}
class Info<T>{
    private T var;
    public void show(){
        System.out.println("var==============="+var);
    }
    public Info(T var) {
        this.var = var;
    }
    public Info() {
    }
    public T getVar() {
        return var;
    }
    public void setVar(T var) {
        this.var = var;
    }
}

2.4.泛型接口

上面那些例子都是使用泛型类。而在jdk1.5以后,泛型也可以定义在接口上了,定义接口的泛型和定义泛型类语法相似。

语法:

public interface 接口名<泛型标志,泛型标志....>{

//静态常量

//抽象方法

}

类如何实现泛型接口 代码展示:

public class JieKouTest {
    public static void main(String[] args) {
        Upan u=new Upan();
        u.name="小可爱";
        Mouse<String> mouse=new Mouse<>();
        mouse.t="5555";
        System.out.println(mouse.fun());
        System.out.println(u.fun());
    }
}
interface USB<T>{
    public static final String NAME="";//常量的命名必须全部大写
    public T fun();
    //JDK1.8后新特性
    default void fun2(){
    }
    static void fun3(){
    }
}
//子类也实现泛型和父类名相同的泛型
class Mouse<T> implements USB<T>{
    T t;
    @Override
    public T fun() {
        return t;
    }
}
//子类在实现接口时,确定泛型类型
class Upan implements USB<String>{
    public String name;
    @Override
    public String fun() {
        return name;
    }
}

2.5.泛型方法

前面学习的所有泛型操作都是将整个类进行泛型化,但同样也可以在类中定义泛型化的方法。泛型方法的定义与其所在的类是否是泛型类是没有任何关系的,所在的类可以是泛型类,也可以不是泛型类。

【泛型方法的简单定义】

[访问权限] <泛型标识> 泛型标识 方法名称(泛型标识 参数名称)

代码展示:

public class factorTest {
        String hello = Student.fun("hello");
        Integer fun = Student.fun(25);
        Double fun1 = Student.fun(25.0);
         System.out.println(hello+"--"+fun+"--"+fun1);
}
class Student{
    //泛型方法: static静态成员,随着类的加载而被加载到JVM内存中 常量池
    public static <T> T fun(T t){
        return t;
    }
    //泛型方法: static静态成员,随着类的加载而被加载到JVM内存中 常量池
    public static <T> Info<?> fun1(Info<? extends T> t){
        return t;
    }
}
class Info<T>{
}

3.java高级--注解

注释: java不会编译注释的内容,注释给程序员看的。

注解: 它是程序看,当程序看到这个注解时,就应该解析它。

譬如: @Controller @Override

注解的分类:

1. 预定义注解

2. 自定义注解

3. 元注解

3.1.预定义注解

预定义注解就是JDK自带的一些注解,该注解被JVM而解析。

1. @Override: 重写得注解。符合重写得规则。

2. @Deprecated: 表示已过时。

3. @SuppressWarnings: 表示压制警告。

4. @FunctionInterface: 表示函数式接口。表示该接口中有且仅有一个抽象方法。

3.2.自定义注解(初级)

语法:

public可以省略

public @interface 注解名{

//注解属性

}

代码展示:

public class Test {
    public static void main(String[] args) {
        Info i=new Info();
        i.name="张三";
        i.show();
    }
}
//定义好注解了
@interface My{
   //注解属性
}
//使用注解
@My
class Info{
    @My
    public String name;
    @My
    public void show(){
        System.out.println("show================="+name);
    }
}

注意: 使用注解和不使用注解没有区别

注解本身没有任何意义,它只有被解析了,才会赋予真正的意义。

我们后会使用反射来对象注解进行解析。

像:@Override 它被JVM解析,从而使其具有相应的意义。

​ @Controller @RequestMapping 它被Spring框架解析,所以具有相应的意义。

3.3.元注解

定义在注解上的注解称为元注解。

@Controller它只能加在类上 @Override它只能加在方法上。

原因它使用了元注解可以设置注解使用的位置

1. @Target(value=可以取下面这些内容): 作用限制注解使用得位置。

/** 表示可以作用在类,接口,枚举 */ TYPE,

/** 属性 */

FIELD,

/** 普通方法上 */

METHOD,

/** 方法参数 */

PARAMETER,

/** 构造方法上 */

CONSTRUCTOR,

/** 局部变量 */

LOCAL_VARIABLE

2. @Retention: 注解什么时候生效。默认时源码 java经历了那些阶段。

源码阶段-->字节码阶段--->运行阶段 /** * 源码时生效 */ SOURCE,

/**

* 字节码时生效 */ CLASS,

/**

* 运行时生效。 * 在JVM内存中还有该注解。 都会被设置为运行时有效 */ RUNTIME

3. @Documented 当生产API文档时该注解还存在。

4. @Inherited 是否运行被子类继承。

3.4.自定义注解(高级)

@RequestMapping("/hello") 因为它定义@RequestMaping注解中有属性。

@interface 注解名{

数据类型 属性名() default 默认值;

}

数据类型: 基本类型,字符串类型,枚举类型【常量】,注解类型,数组类型【必须是上面这些类型的数组】

代码展示:

public class Test {
    public static void main(String[] args) {
        Info i=new Info();
        i.name="张三";
        i.show();
    }
}
//定义好注解
//表示该注解可以使用的位置
@Target(value = {ElementType.TYPE,ElementType.METHOD})
//表示注解什么时候生效--source--class[默认字节码有效]---runtime[反射时验证]
@Retention(value = RetentionPolicy.RUNTIME)
//是否在生成api文档时存在该注解
@Documented
//子类是否能继承该注解,如果注解在定义时使用了下面这个元注解则能被子类继承。
@Inherited
@interface My{
    String value(); //如果设置default默认值,那么在使用该注解时可以不为该属性赋值。
    int age() default 15;
    String[] hobby() default {};//
}
//使用注解 如果使用注解时有且仅有一个属性没有赋值,而且该属性的名字value那么在给该属性赋值值,可以省略value,当写其他内容时,不能省略value
@My(value = "hello",hobby = "游泳")
class Info{
    public String name;
    public void show(){
        System.out.println("show================="+name);
    }
}
class Student extends Info{
}

到此这篇关于Java泛型与注解全面分析讲解的文章就介绍到这了,更多相关Java泛型与注解内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 一文带你深入了解Java泛型

    目录 什么是Java泛型 泛型的使用 泛型类 泛型接口 泛型方法 泛型的底层实现机制 ArrayList源码解析 什么是泛型擦除 泛型的边界 ?:无界通配符 extends 上边界通配符 super 下边界通配符 PECS原则 泛型是怎么擦除的 擦除类定义中的无限制类型参数 擦除类定义中的有限制类型擦除 擦除方法定义中的类型参数 桥接方法和泛型的多态 泛型擦除带来的限制与局限 泛型不适用基本数据类型 无法创建具体类型的泛型数组 反射其实可以绕过泛型的限制 什么是Java泛型 Java 泛型(ge

  • Java实例讲解注解的应用

    目录 1.注解的理解 2.@Override 3.@Deprecated 4.@SuppressWarnings 1.注解的理解 1)注解(Annotation)也被称为元数据(Metadata),用于修饰解释包. 类.方法.属性.构造器.局部变量等数据信息. 2)和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于 嵌入在代码中的补充信息. 3)在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略 警告等.在JavaEE中注解占据了更重要的角色,例如用来配置应用程序的任

  • Java利用泛型实现折半查找法

    目录 泛型化的折半查找法 1.题目 2.解题思路 3.代码详解 知识点补充 泛型化的折半查找法 1.题目 泛型是JAVA重要的特性,使用泛型编程,可以使代码复用率提高. 实现:查找作为泛型的一个简单应用,使用泛型实现折半查找法 2.解题思路 创建一个类:BinSearch. 折半查找要求数据集合中的元素必须可比较,并且各元素按升序或降序排列.取集合的中间元素作为比较对象,如: (1)如果给定的值与比较对象相等,则查找成功,返回中间元素的序号. (2)如果给定的值大于比较对象,则在中间元素的右半段

  • 详解Java如何实现自定义注解

    目录 概念 作用 JDK中预定义的一些注解 注解生成文档案例 自定义注解 格式 本质 属性:接口中的抽象方法 元注解:用于描述注解的注解 在程序使用(解析)注解:获取注解中定义的属性值 案例:通过自定义注解定义一个简单的测试框架 总结 概念 概念:说明程序的.给计算机看的 注释:用文字描述程序的.给程序员看的 定义:注解(Annotation),也叫元数据.一种代码级别的说明.它是JDK1.5及以后版本引入的一个特性,与类.接口.枚举是在同一个层次.它可以声明在包.类.字段.方法.局部变量.方法

  • Java使用通配符实现增强泛型详解

    目录 使用通配符增强泛型 1.题目 2.解题思路 3.代码详解 知识点补充 使用通配符增强泛型 1.题目 泛型是JAVA重要的特性,使用泛型编程,可以使代码复用率提高. 实现:在泛型方法中使用通配符 2.解题思路 创建一个类:WildcardsTest. 创建一个方法getMiddle()用于获得给定列表的中间值. 在泛型中,使用“?”作为通配符,通配符的使用与普通的类型参数类似,如通配符可以利用extends关键字来设置取值的上限.如 <? extends Number> 表示Byte,Do

  • Java注解详解及实现自定义注解的方法

    目录 概念 ‍♀️作用 ⛹JDK中预定义的一些注解

  • java基础之反射和泛型以及注解

     java基础之反射和泛型以及注解 泛型擦除 泛型擦除: 泛型只在编译时期有效,编译后的字节码文件中不存在泛型信息. 声明泛型集合,集合两端类型必须一致.类型也可以用包装类型,泛型的类型必须是引用类型,不能为基本类型. 实现公用的类和方法,对公用的业务进行抽取. 泛型方法/泛型类/泛型接口 public class GenericTest { /** * 泛型声明,定义泛型方法 * @param <T> * @param <K> * @param t * @param k */ p

  • Java知识梳理之泛型用法详解

    目录 泛型 作用 集合中泛型 自定义泛型 通配符 2.注意点 3.有限制的通配符 泛型 背景: 从JDK 5.0以后,Java引入了“参数化类型(Parameterized type)”的概念,允许我们在创建集合时再指定集合元素的类型,正如:List ,这表明该List只能保存字符串类型的对象. 作用 解决元素存储的安全性问题,好比商品.药品标签,不会弄错. 解决获取数据元素时,需要类型强制转换的问题,好比不用每回拿商品.药品都要辨别. @Test public void test1(){ Ar

  • Java使用泛型实现栈结构的示例代码

    目录 使用泛型实现栈结构 1.题目 2.解题思路 3.代码详解 多学一个知识点 使用泛型实现栈结构 1.题目 泛型是JAVA重要的特性,使用泛型编程,可以使代码复用率提高. 实现:使用泛型实现栈结构 2.解题思路 创建一个泛型类:Stack. 定义3个方法,入栈的push方法,出栈的pop方法,还有判断栈是否为空的empty()方法. 在底层实现上,使用LinkedList作为容器. 泛型类是含有一个或多个类型参数的类.定义泛型类很简单,只需要在类的名称后面加上“<”和“>”,并在其中指明类型

  • Java泛型与注解全面分析讲解

    目录 1.什么是泛型 2.为何使用泛型 2.1.如何定义泛型 2.2.通配符 2.3.受限泛型 2.4.泛型接口 2.5.泛型方法 3.java高级--注解 3.1.预定义注解 3.2.自定义注解(初级) 3.3.元注解 3.4.自定义注解(高级) 1.什么是泛型 其实我们在使用集合时就用过泛型List<T> 创建一个List对象List<Student> list=new ArrayList():<T>它就是泛型. 所谓的泛型就是在类定义时,不为类中属性和方法指定数据

  • Java @GlobalLock注解详细分析讲解

    目录 GlobalLock的作用 全局锁 为什么要使用GlobalLock 工作原理 GlobalLock的作用 对于某条数据进行更新操作,如果全局事务正在进行,当某个本地事务需要更新该数据时,需要使用@GlobalLock确保其不会对全局事务正在操作的数据进行修改.防止的本地事务对全局事务的数据脏写.如果和select for update组合使用,还可以起到防止脏读的效果. 全局锁 首先我们知道,seata的AT模式是二段提交的,而且AT模式能够做到事务ACID四种特性中的A原子性和D持久性

  • Java Array.sort()源码分析讲解

    阅读起点: Arrays.sort(nums1); 使用ctrl+左键进入sort()方法 1.Arrays.sort() 关于sort()的方法一共有14个,就目前调用的来看是以下这种最基础的. public static void sort(int[] a) { DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0); } 2.DualPivotQuicksort DualPivotQuicksort即双轴快排,定义了七种原始类型的排序

  • Java详细分析讲解泛型

    目录 1.泛型概念 2.泛型的使用 2.1泛型类语法 2.2泛型方法语法 2.3泛型接口语法 2.4泛型在main方法中的使用 3.擦除机制 4.泛型的上界 5.通配符 5.1通配符的上界 5.2通配符的下界 6.包装类 6.1装箱和拆箱 1.泛型概念 泛型就是将类型参数化 所谓类型参数化就是将类型定义成参数的形式,然后在使用此类型的时候的时候再传入具体的类型 到这我们可以看出来:泛型在定义的时候是不知道具体类型的,需要在使用的时候传入具体的类型,泛型可以用在类.接口和方法中,这样做的好处是一个

  • 分析讲解SpringMVC注解配置如何实现

    目录 简介 注解类代替web.xml 注解类代替Spring-mvc.xml 简介 使用配置类和注解代替web.xml和SpringMVC配置文件的功能 在Servlet3.0环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类,如果找到的话就用它来配置Servlet容器. Spring提供了这个接口的实现,名为SpringServletContainerInitializer,这个类又会查找实现WebApplicationI

  • Java分析讲解序列化与字典功能的序列化

    目录 两种解决方案 字典注解定义 字典序列化与返序列化器的实现 字典序列化与反序列工具类 字典转换服务类 字典缓存服务 两种解决方案 前端查询字典数据然后前端转码 后端查询字典值,然后再转码返回给前段. 本文及时针对方案2 进行的改进 目标: 在需要返回给前段的字段上添加指定的注解例如:@DictDesc 则根据该字段定义的值结合注解配置生成 xxxDesc字段并自动赋值为注解属性值所对应的字典描述: 具体使用的技术涉及到jackson序列化与反序列化,其他JSON工具包也类型的效果; 字典注解

  • Spring Boot示例分析讲解自动化装配机制核心注解

    目录 1. 自动化装配介绍 2. Spring Boot 自动化配置UML图解 3. Spring Boot 自动化配置核心注解分析 3.1 @Inherited 3.2 @SpringBootConfiguration 3.3 @EnableAutoConfiguration 3.4 @ComponentScan 3.5 @ConfigurationPropertiesScan 3.6 @AutoConfigurationImportSelector 3.7 @AutoConfiguratio

  • 详细分析Java 泛型的使用

    一.泛型的简介 1.为什么要使用泛型? 一般使用在集合上,比如现在把一个字符串类型的值放入到集合里面,这个时候,这个值放到集合之后,失去本身的类型,只能是object类型.这时,如果想要对这个值进行类型转换,很容易出现类型转换错误,怎么解决这个问题,可以使用泛型来解决. 2.在泛型里面写是一个对象,String 不能写基本的数据类型 比如int,要写基本的数据类型对应的包装类 基本数据类型 对应包装类 基本数据类型 对应包装类 byte Byte short Short int Integer

  • Java 数组高频考点分析讲解

    目录 1.数组理论基础 2.常见考点 1.二分查找 2.移除元素 1.数组理论基础 数组是存放在连续内存空间上的相同类型数据的集合,可以通过下标索引的方式获取到下标下对应的数据. 举个栗子(字符数组)~ 可以看到: 1.数组的下标从0开始 2.数组在内存中的地址是连续的 所以在删除元素时,只能用覆盖的方式进行. 例如,要删除下标为2的元素~ 就需要将从2之后的元素依次移到前一个,覆盖掉要删除的元素. 所以删除元素并不是将该元素的空间释放了,而是将后面的元素移到前面,覆盖掉要删除的元素,然后将数组

随机推荐