泛型是 Java SE5 出现的新特性,泛型的本质是类型参数化或参数化类型,在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型
一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。
Java 在引入泛型之前,表示可变对象,通常使用 Object 来实现,但是在进行类型强制转换时存在安全风险。有了泛型后:
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();
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对象是可以给这个类赋予不同类型,(只能赋予引用类型)泛型的使用使得类型的定义更加灵活了,不像以前是直接在类里定义死的,使用强转又有风险。
在开发中对象的引用传递是最常见的,但是如果在泛型类的操作中,在进行引用传递时泛型类型必须匹配才可以传递,否则是无法传递的。
泛型用问号代替是泛型的通配符
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类型的数据
泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
泛型的类型参数可以有多个。
泛型的参数类型可以使用extends语句,例如
泛型的参数类型还可以是通配符类型。例如Class> classType = Class.forName(java.lang.String
[设置上限]
声明对象: 类名称 extends 类> 对象名称;
定义类: [访问权限] 类名称<泛型标识 extends 类>{}
[设置下限]
声明对象: 类名称 super 类> 对象名称;
定义类: [访问权限] 类名称<泛型标识 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
public interface 接口名<泛型标识,....>{
}
接口用来被类实现。一个类如何实现泛型接口。有两种方式
(1)在实现泛型接口时为泛型接口指定类型。
(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);
}
}
[访问权限] <泛型标识> 泛型标识 方法名称(泛型标识 参数名称){
}
public T fun(T b){
System.out.println(b);
return b;
}
预定义注解是指 Java 语言中已经定义好的注解,可以直接使用。Java SE 提供了许多预定义注解,这些注解在 JDK 中已经实现,并且提供相应的处理器对注解进行处理,@Override重写,@Deprecated标记一些过时的方法,这些都是预定义注解,就是javaJDK本身就有的注解0
自定义注解字面意思就是自己按照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;
}
}
自定义注默认是可以加在类,方法,参数等等上,要想对其有限制这就需要用到注解的原注解了
元注解是加在注解上的注解限制预定义注解和自定义可以在类,方法,参数,构造函数等等使用的注解。
TYPE, // 类、接口、枚举类
FIELD, // 成员变量(包括:枚举常量)
METHOD, // 成员方法
PARAMETER, // 方法参数
CONSTRUCTOR, // 构造方法
LOCAL_VARIABLE, // 局部变量
ANNOTATION_TYPE, // 注解类
PACKAGE, // 可用于修饰:包
TYPE_PARAMETER, // 类型参数,JDK 1.8 新增
TYPE_USE // 使用类型的任何地方,JDK 1.8 新增
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 {}