java泛型和注解

1、什么是泛型

1.1泛型的概念

泛型是 Java SE5 出现的新特性,泛型的本质是类型参数化或参数化类型,在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型

1.2泛型的意义

一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。

Java 在引入泛型之前,表示可变对象,通常使用 Object 来实现,但是在进行类型强制转换时存在安全风险。有了泛型后:

  • 编译期间确定类型,保证类型安全,放的是什么,取的也是什么,不用担心抛出 ClassCastException 异常。
  • 提升可读性,从编码阶段就显式地知道泛型集合、泛型方法等处理的对象类型是什么。
  • 泛型合并了同类型的处理代码提高代码的重用率,增加程序的通用灵活性

2、为什么使用泛型和泛型使用

  2.1为什么使用泛型

  public static void main(String[] args) {
        List   arr = new ArrayList();
        arr.add("111");
        arr.add(111);
        for (int i = 0; i < arr.size(); i++) {
          String o = (String) arr.get(i);
            System.out.println(0);


        }


    }
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
	at Dome01.textfc.main(textfc.java:13)

ArrayList可以存放任意类型,例子中添加了一个String类型,添加了一个Integer类型,取值的时候都以字符串的方式取值,因此程序崩溃了。为了解决类似这样的问题(在编译阶段就可以解决),泛型应运而生。

​
  List arr = new ArrayList();

​

2.2泛型的使用和泛型类的使用

public class 类名<泛型标志,泛型标志.....>{
// <>尖括号里面可以写多个泛型 以逗号隔开

    public 泛型标志 属性名;

}
--泛型标志可以是任意字符。习惯使用T

以下代码是泛型的使用

public class fx {
    private T  x ;
    private T y ;
}
public class fxText {
    public static void main(String[] args) {
        fx stringx = new fx<>("1","2");
        fx integerfx = new fx<>(1,2);
        fx doublefx = new fx<>(1.1,1.2);


    }
}

定义一个类,然后在主方法区去使用 代码中可以看到当new对象是可以给这个类赋予不同类型,(只能赋予引用类型)泛型的使用使得类型的定义更加灵活了,不像以前是直接在类里定义死的,使用强转又有风险。

3、泛型的通配符

3.1泛型通配符的定义

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

3.2通配符的格式

泛型用问号代替是泛型的通配符

static void fun(tpf tpf){
       System.out.println("+++"+tpf.getX());


    }

3.3通配符的使用

public class tpf {
    private  T x;

    public tpf() {
    }

    public tpf(T x) {
        this.x = x;
    }
public class text {
    public static void main(String[] args) {
        tpf integertpf = new tpf<>(111);
        tpf stringtpf = new tpf<>("222");
        fun(stringtpf);
        fun(integertpf);

    }

static void fun(tpf tpf){
       System.out.println("+++"+tpf.getX());


    }

}

由代码可以看到fun方法用了泛型的通配符可以接收Integer,string类型的数据

4、泛型的上限和下限

4.1泛型的受限规则

泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
泛型的类型参数可以有多个。
泛型的参数类型可以使用extends语句,例如。习惯上称为“有界类型”。
泛型的参数类型还可以是通配符类型。例如Class classType = Class.forName(java.lang.String


4.2泛型的上限下限制使用

[设置上限]
声明对象: 类名称 对象名称;
定义类:  [访问权限] 类名称<泛型标识 extends 类>{}

[设置下限]
声明对象: 类名称 对象名称;
定义类:  [访问权限] 类名称<泛型标识 super 类>{}

以下代码是泛型受限的使用方法

public class Info {
    private T x;
    public  void  fun (){


        System.out.println("111111");
    }


}
public class text {
    public static void main(String[] args) {
        Info numberInfo = new Info<>();
        Info objectInfo = new Info<>();
        fa(numberInfo);
        fa1(objectInfo);


    }
//泛型的上限不能小于本身泛型 这里也就是( Number)
    public  static  void  fa(Info info){
        info.fun();



    }
//泛型的下限就是不能小于本身必须大于或者等于本身这里也就是( Number)
    public  static  void  fa1(Info info){
        info.fun();


}
     
  

5、泛型接口

5.1泛型接口规则和语法

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

}

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

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

(2) 该类也是一个泛型类,而且该类使用的泛型标志必须和接口的标志一致。

5.2泛型方法的使用和实现

public class Text {
    public static void main(String[] args) {
//通过new类名字的方法来调用没用静态修饰的的方法;
        fa fa = new fa();
        fa.show("111");
         //因为该类实现泛型接口是使用泛型所以可以再new的时候给其定义类型
        fa1 integerfa1 = new fa1<>();
        integerfa1.show(22);

    }

}
//用这个类来实现泛型接口然后给其类型
class fa implements Usb{


    @Override
    public void show(String s) {
        System.out.println(s);

    }
}
//实现泛型接口并继续使用泛型
class fa1 implements Usb{

    @Override
    public void show(T t) {
        System.out.println(t);

    }
}

6、泛型的方法

6.1泛型方法的语法

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

}

public    T  fun(T b){


        System.out.println(b);
        return b;
    }

 7、注解

7.1预定义注解

预定义注解是指 Java 语言中已经定义好的注解,可以直接使用。Java SE 提供了许多预定义注解,这些注解在 JDK 中已经实现,并且提供相应的处理器对注解进行处理,@Override重写,@Deprecated标记一些过时的方法,这些都是预定义注解,就是javaJDK本身就有的注解0

7.3自定义注解

自定义注解字面意思就是自己按照java提供的语法自己定义意注解

自定义注解语法如下:

权限访问符 @interface 注解名{​}

自定义注解的实现代码

@interface  zj{};
@zj
public class Text {
    @zj
    public static void main(String[] args) {
        Text text = new Text();
        String fun = text.fun("111");
        Text text1 = new Text();
        Integer fun1 = text1.fun(2222);

    }
    @zj
    public    T  fun(T b){


        System.out.println(b);
        return b;
    }
}

自定义注默认是可以加在类,方法,参数等等上,要想对其有限制这就需要用到注解的原注解了

7.3元注解

元注解是加在注解上的注解限制预定义注解和自定义可以在类,方法,参数,构造函数等等使用的注解。

@Target注解

  TYPE, // 类、接口、枚举类
 
    FIELD, // 成员变量(包括:枚举常量)
 
    METHOD, // 成员方法
 
    PARAMETER, // 方法参数
 
    CONSTRUCTOR, // 构造方法
 
    LOCAL_VARIABLE, // 局部变量
 
    ANNOTATION_TYPE, // 注解类
 
    PACKAGE, // 可用于修饰:包
 
    TYPE_PARAMETER, // 类型参数,JDK 1.8 新增
 
    TYPE_USE // 使用类型的任何地方,JDK 1.8 新增

@Retention注解

SOURCE,    // 源文件保留
    CLASS,       // 编译期保留,默认值
    RUNTIME   // 运行期保留,可通过反射去获取注解信息

以下代码是原注解的使用

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.CONSTRUCTOR,ElementType.PARAMETER})
@interface  zj{};

当@Target注解只有一个值并且是value属性的话可以省略value和大括号

原注解属性定义

@interface  zj{
    String value() default "" ;
// default表示默认

};

元注解的属性可以加 default给默认值亦可以不给不给的话就要在加注解时自己给了

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.CONSTRUCTOR,ElementType.PARAMETER})
@interface  zj{
    String value() default "" ;
//未给默认值
    int age() ;


};
//在加注解的时候就要自己给值了
@zj(age = 18)
public class Text {}

你可能感兴趣的:(java,开发语言)