1.什么是泛型?
在定义类时,不会给定义类中成员(属性 方法的返回类型 方法的参数),而在类对象创建时为其指定相应的数据类型。
2.为什么用泛型?
使用泛型,在给类中属性赋值时可以赋值任意类型,也可以解决数据类型安全问题。
3如何定义泛型?
语法:
public class 类名<泛型标志,......>{
private 泛型标志 属性名;
}
public class Demo1<T> { private T xiao; private T da;public Demo1() { } public Demo1(T xiao, T da) { this.xiao = xiao; this.da = da; } /** * 获取 * @return xiao */ public T getXiao() { return xiao; } /** * 设置 * @param xiao */ public void setXiao(T xiao) { this.xiao = xiao; } /** * 获取 * @return da */ public T getDa() { return da; } /** * 设置 * @param da */ public void setDa(T da) { this.da = da; } public String toString() { return "demo{xiao = " + xiao + ", da = " + da + "}"; } }
public class Test1 { public static void main(String[] args) { Demo1<String> tdemo = new Demo1<String>("花","草"); System.out.println(tdemo); Demo1<Integer> integerdemo = new Demo1<Integer>(1,2); System.out.println(integerdemo); } }
注意:指定泛型应用类型时,这种泛型类型必须使用引用类型。
4.通配符
在开发中对象的引用传递是最常见,在泛型传递操作中,在传递泛型中必须相同才能传递,否则无法传递。
public class Demo2<T> { private T x; public T getX() { return x; } public void setX(T x) { this.x = x; } public void show(){ System.out.println(x); } }public class Test2 { public static void main(String[] args) {Demo2<String> stringDemo21 = new Demo2<String>(); stringDemo21.setX("string"); fun3(stringDemo21); Demo2<Integer> integerDemo21 = new Demo2<Integer>(); integerDemo21.setX(123); fun3(integerDemo21); }public static void fun3(Demo2<?> info3){ info3.show(); }//能否该方法让它可以接受任意的泛型类型。必须使用通配符 < ?> 为泛型的通配符
4.1受限泛型
在引用传递中,在泛型操作中也可以设置一个泛型对象的范围上限和范围下限。范围上限使用extends关键字声明,表示参数化的类型可能是所指定的类型或者是此类型的子类,而范围下限使用super进行声明,表示参数化的类型可能是所指定的类型或者此类型的父类型。
public class Test2 { public static void main(String[] args) { Demo2<Integer> integerDemo2 = new Demo2<Integer>(); integerDemo2.setX(18); Demo2<String> stringDemo2 = new Demo2<String>(); stringDemo2.setX("19"); fun(integerDemo2); Demo2<Number> numberDemo2 = new Demo2<Number>(); numberDemo2.setX(22); fun2(numberDemo2); } //通配符下限 //泛型的下限--泛型的类型 不能小于Number 要么为Number类型要么为Number的父类类型。 public static void fun2(Demo2<? super Number> info2){ info2.show(); } //通配符上限 //泛型上限:---泛型类型不能超过Number 要么为Number类型要么为Number的子类类型 public static void fun(Demo2<? extends Number> info){ info.show(); } }
5.泛型接口
(1)在实现泛型接口时为泛型接口指定类型。
(2) 该类也是一个泛型类,而且该类使用的泛型标志必须和接口的标志一致。
public interface Mouse<T> { public abstract void USB(T t); }
public class Test3 { public static void main(String[] args) { A a = new A(); a.USB("aaa"); B<Integer> b = new B<Integer>(); b.USB(123); } } //1.类实现泛型接口时为其指定泛型类型。 class A implements Mouse<String>{ public void USB(String s ) { System.out.println(s+"+++++"); }}
class B<T> implements Mouse<T> { //第二种 类实现接口时该类也设置为泛型类,标志必须和接口的泛型标志一致 public void USB(T x){ System.out.println(x+"++++"); } }
6.泛型方法
前面学习的所有泛型操作都是将整个类进行泛型化,但同样也可以在类中定义泛型化的方法。泛型方法的定义与其所在的类是否是泛型类是==没有任何关系的==,所在的类可以是泛型类,也可以不是泛型类。
public static void main(String[] args) { Test4 test4 = new Test4(); String ssss = test4.fun("ssss"); Integer fun = test4.fun(111111); } public <T> T fun(T z){ System.out.println(z); return z; } }7.注解
7.1预定义注解?
运行时被读取,并执行相应的处理,以便于其他工具补充信息或者进行部署。
@Override: 当方法使用该注解时,表示该方法是一个重写的方法,那么该方法必须符合重写的规则【子类重写的方法名必须和父类的方法名一致,参数也要一致,返回值也要一致 访问修饰不能小于父类的<public protected 默认 private> 抛出的异常不能大于父类】。
@Deprecated: 标记该方法已经过时。JVM
@FuncationInterface: 函数式接口.---要求接口钟有且仅有一个抽象方法
7.2自定义注解
public static void main(String[] args) { Test5 test5 = new Test5(); test5.setName("xishi"); test5.setValue(23); test5.fun("xishi",23); } @interface you{ //自定义注解 } @you private String name; @you private Integer value; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getValue() { return value; } public void setValue(Integer value) { this.value = value; } @you public void fun(@you String name,@you Integer value){ System.out.println(name+value); } }
使用自定义注解没有任何意义,想让它有意义必须结合反射来解释注解,并赋予其相应作用
@Override:----JVM解析了该注解
@Controller:---spring框架解析了该注解。
7.3元注解
限制注解的使用范围,使用用元注解来限制。
@Retention:用来限制注解什么时候生效
//源码时生效
SOURCE,//字节码时生效
CLASS,//运行时生效。反射。
RUNTIME
@Targer:该注解用在什么地方
//使用在类上
TYPE,//使用在属性上
FIELD,//使用在方法上
METHOD,//使用在参数
PARAMETER,//使用在构造方法上
CONSTRUCTOR
@Documented: 在生成api文档是是否含有该注解。
//在类型上,属性上,方法上 @Target(value = {ElementType.TYPE,ElementType.FIELD,ElementType.METHOD}) //字节码时生效 @Retention(RetentionPolicy.CLASS) //在生成api文档时,是否还有该注解 @Documented public @interface On { }
@On public class Test6<T> { public static void main(String[] args) { In<String> stringIn = new In<String>(); stringIn.setKey("草"); stringIn.setValue("花"); In<Integer> integerIn = new In<Integer>(); integerIn.setValue(13); integerIn.setKey(14); fun(stringIn); fun(integerIn); } public static void fun(In<?> info){ info.show(); } } class In<T> { @On private T key; @On private T value; public void show() { System.out.print(value); System.out.println(key); } public T getKey() { return key; } public void setKey(T key) { this.key = key; } public T getValue() { return value; } public void setValue(T value) { this.value = value; } }
定义的注解只能在 类型,方法,属性上使用
再生成api时,含有注解
生成api文档
7.4自定义注解--【属性】
@Target(value = {ElementType.TYPE,ElementType.FIELD,ElementType.METHOD}) @Retention(value = RetentionPolicy.RUNTIME)//运行有效 @interface fly{ String value() default ""; int age() default 18; String[] name() default {}; } //如果只有value赋值,value属性名可以省略 //default 设置默认值,没有给定值就会用默认值 //如果给定数组时是一个可以省略{},如果多个就要加上{} @fly(value = "he",age=20,name ={"花","草"}) class flyer{ }