java泛型和注解的讲解

1,什么是泛型

2,为什么使用泛型

3,如何定义泛型

4,通配符和泛型的限制

5,如果定义泛型接口

6,如果定义泛型方法

7,注解

7.1预定义注解

7.2自定义注解

7.3元注解

1,什么是泛型

泛型(Generics)是一种在编译时期提供类型安全性的机制。它允许在定义类、接口或方法时使用参数化类型,这样就可以在使用时指定具体的类型。

使用泛型的好处是可以编写通用的、可重用的代码,同时保证类型的安全性。通过泛型,我们可以在编译时期检查类型,避免在运行时出现类型转换错误。

泛型可以应用于类、接口、方法等,使用一对尖括号(<>)来指定泛型类型。

2,为什么使用泛型

比如在使用Object类型时,需要进行强制类型转换。如果在进行类型转换时出现错误,可能会在运行时抛出ClassCastException异常。这种类型转换错误只能在运行时被检测到,因此存在一定的安全隐患。

而使用泛型(Generics),可以在编译时期就对类型进行检查,提供了更强的类型安全性。使用泛型,我们可以在定义类、接口或方法时指定参数化类型,从而在使用时避免类型转换错误 

如下图所示出现的类型转化异常(ClassCastException):

@Data
@AllArgsConstructor
@NoArgsConstructor
public 代码class Point {        *//**创建一个坐标位置类
\*    private Object x;
    private Object y;
}
package com.gll.date0809.test.t1;
​
public class Test01 {
    public static void main(String[] args) {
        //x和y的值都是整型
        Point point = new Point(130, 88);
        //x和y都是字符串类型
        Point point1 = new Point("东经35", "北纬138");
        //不同类型代码
        Point point2 = new Point("东经66", 255);
​
        String x = (String) point2.getX();
        String y = (String) point2.getY();
        //当运行时会报错classCastException
​
    }
}
​

3,如何定义泛型

语法:

public class 类名<泛型标志,泛型标志......>{
    private  泛型标志 属性名;
    //泛型可是是任何字符,习惯用T表示
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Point2<T> {
    private T x;
    private T y;
​
}
​
class test02{
    public static void main(String[] args) {
        Point2<String> stringPoint2 = new Point2<>("东经101", "北纬35");
        String x = stringPoint2.getX();
        String y = stringPoint2.getY();
​
        //编译时类型
        List<String> list = new ArrayList<>();
        list.add("Hello");
        list.add(123);  // 编译时报错
​
        String str = list.get(1);//编译时类型检查,不再需要类型转换
    }
}

注意:指定泛型类型时,必须为引用类型。

4,通配符

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

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Info3<T> {
    private T var;
    public void show(){
        System.out.println("今天立秋,天气很好,"+var);
    }
}
​
class Test3{
    public static void main(String[] args) {
        Info3<String> stringInfo3 = new Info3<>();
        stringInfo3.setVar("继续加油吧!");
        fun(stringInfo3);
    }
​
    public static  void fun(Info3<?> info){//能否该方法让它接收任意的泛型类型,则必须使用通配符,?是泛型的通配符
        info.show();
    }
}

4.2受限泛型

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

public class Test4 {
    public static void main(String[] args) {
        Info4<String> stringInfo4 = new Info4<>();
        Info4<Integer> integerInfo4 = new Info4<>();
        Info4<Object> objectInfo4 = new Info4<>();
        Info4<Number> numberInfo4 = new Info4<>();
​
        fun1(stringInfo4);//String 报错,String不是Number的子类
        fun1(integerInfo4);
        fun1(numberInfo4);
​
        fun2(integerInfo4);//integer 报错,integer 不是Number的父类
        fun2(objectInfo4);
​
    }
    //泛型的上限,--泛型的类型不能超过Number,要么是Number,要么是Number的子类类型;
    public static void fun1(Info4<? extends Number> info4){
        info4.show();
    }
    //泛型的下限,--泛型的类型不能小于Number,要么是Number,要是是Number的父类(Object);
    public static void fun2(Info4<? super Number> info4){
        info4.show();
    }
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Info4<T> {
    private T var;
    public void show(){
        System.out.println("今天立秋,天气很好,"+var);
    }
​
}

5,泛型接口

语法:

public interface 接口名 <泛型标识,......>{
​
}

接口用来被类实现,一个类如何实现泛型接口,有两种方式:

(1)在实现泛型接口时为泛型接口指定类型

(2)该类也是泛型类,而且该类所使用的泛型标识必须和该接口的泛型标识一样

public class Test5 {
    public static void main(String[] args) {
        Mouse mouse = new Mouse();
        mouse.show("来自郑州");
        KeyBoard<Integer> integerKeyBoard = new KeyBoard<>();
        integerKeyBoard.show(88);
    }
}
​
public interface USB <T>{
    public abstract void show(T t);
}
​
//第一种使用泛型接口时为其指定类型
class Mouse implements USB<String>{
    @Override
    public void show(String s) {
        System.out.println("我使用的是罗技鼠标"+s);
    }
}
​
//第二种类实现接口时,类也定义为泛型类,且该类泛型标准必须和接口泛型标志一致
class KeyBoard<T> implements USB<T>{
​
    @Override
    public void show(T t) {
        System.out.println("我使用的是惠普键盘"+t);
    }
}
​

6,泛型方法

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

泛型方法语法:

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

}

public class Test6 {
    public static void main(String[] args) {
        Test6 test6 = new Test6();
        test6.show(666);
    }
    //泛型方法
    public <T>  void show(T t){
        System.out.println("天黑了,"+t);
    }
}
​

7.注解

Java注解(Annotation)是一种元数据(metadata)的形式,它可以在Java代码中添加额外的信息、标记或说明。注解可以用于类、方法、字段、参数等元素上,用于提供给编译器、工具和运行时环境使用。

Java注解的语法使用@符号后跟注解的名称,放置在目标元素的前面。

7.1预定义注解

@Override: 当方法使用该注解时,表示该方法是一个重写的方法,那么该方法必须符合重写的规则

【子类重写的方法必须和父类的方法名一致,参数一致,返回值也要一致,访问修饰符不能小于父类的<public protected 默认 private> 抛出的异常不能大于父类】。

@Deprecated:标记该方法已经过时。jvm

@FuncationInterface: 函数式接口, --要求接口有且仅有一个抽象方法。

7.2自定义注解

语法:

public @interface 注解名{
​
}

使用方法:

@注解名

@注解名
public void show(){
​
}
public class Test7 {
    public static void main(String[] args) {
        Day day = new Day();
        day.rain("下雨");
    }
}
//自定义注解
@interface MyAnnotation{
​
}
@MyAnnotation
class Day{
    @MyAnnotation
    private String weather;
​
    @MyAnnotation
    public void rain(String weather){
        System.out.println("今天,"+weather);
    }
}

使用了自定义注解并没有任何意思,要想让它有意义,必须结合反射来解析这些注解,并赋予相应的功能。

@Override: --jvm解析了该注解。

@Controller: --spring框架解析了该注解。

7.3元注解

思考:@controller只能在类上,@GetMapping 只能使用在方法。为什么这些注解可以限制它的使用范围。因为它们用元注解来限制。

@Retention:限制注解什么时候生效。【源码--javac--字节码--运行】

//使用在类上
TYPE,
//使用在属性上
FIELD,
//使用在方法上
METHOD,
//使用在参数
PARAMETER,
//使用在构造方法上
CONSTRUCTOR,

@Documented: 在生成api文档是否含有该注解。

 

 

7.4自定义注解

语法:

public @interface 注解名{
数据类型 属性名() default 默认值;
//如果没有设置默认值,那么在使用盖饭注解必须为该属性指定值。
}
数据类型可以用哪些类型: 基本类型【8个】,及基本类型的数组。
public class Test7 {
    public static void main(String[] args) {
        Day day = new Day();
        day.rain("xiayu");
    }
}
​
@Target({ElementType.METHOD,ElementType.TYPE,ElementType.FIELD})
​
@Retention(RetentionPolicy.RUNTIME) //使用最多运行时有效,【Source--Class--Runtime】 ,默认值是在字节码生效
@Documented
@interface MyAnnotation{
        String value() default "";
        int age() default 18;
        String[]  hobby() default {};
​
}
//如果是value赋值,那么可以省略属性名
@MyAnnotation(value="hello")//给定的数值只有一个可以省略,多个必须给定属性名
class Day{
    @MyAnnotation
    private String weather;
​
    @MyAnnotation
    public void rain(String weather){
        System.out.println("jintian,"+weather);
    }
}

完。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值