1.什么是泛型
类在定义时,无法确认类中成员的类型(属性,方法),而是类在创建时指定具体的数据类型
List<E> :这里的<E>就是泛型标志,Map<K,V>中<K,V>也是泛型标志
2.为什么要使用泛型
举例:定义一个Point 点类,要求如下
1.坐标值可以是整数 x=15,y=25
2.坐标值也可以都是小数 x=15.5,y=25.5
3.坐标值也可以是字符串类型 x=“北纬15度”y=“东经250度”
2.1 创建 坐标x,y构造函数
package demo01;
public class Point {
private Object x;
private Object y;//因为Object是所有类的父类,而且多态,子类类型可以自动向父类类型转化。
public Point(Object x, Object y) {
this.x = x;
this.y = y;
}
/**
* 获取
* @return x
*/
public Object getX() {
return x;
}
/**
* 设置
* @param x
*/
public void setX(Object x) {
this.x = x;
}
/**
* 获取
* @return y
*/
public Object getY() {
return y;
}
/**
* 设置
* @param y
*/
public void setY(Object y) {
this.y = y;
}
public String toString() {
return "Point{x = " + x + ", y = " + y + "}";
}
}
2.2测试类
package demo01;
public class Test01 {
public static void main(String[] args) {
//整型坐标
Point p1 = new Point(25, 26);
//小数坐标
Point p2 = new Point(25.5, 26.6);
//字符串类型
Point p3 = new Point("北纬25度","东经36度");
//字符串和整型
Point p4 = new Point("北纬35度",15);
String x =(String) p4.getX();//double类型,没有String类型全面
//java.lang.ClassCastException:java.lang.Integer cannot be cast to java.lang.String 类转换异常
//如果使用Object定义类中属性类型,那么可能在后期会出现数据类型安全问题
String y =(String) p4.getY();
}
}
使用Object接收任意参数,可能会出现数据类型安全问题。如何解决上述问题,由于我们无法在类定义时确定类中成员的数据类型,所以我们可以使用泛型来解决数据类型安全问题
3.如何使用泛型
泛型可以解决数据类型的安全性问题,其主要原理是在类声明时通过一个标识表示类中某个属性的数据类型或者是某个方法的返回值及参数类型。这样在类声明或者实例化时只要指定好需要的类型即可。
语法:
public class 类名<T,E,B>{
private T a;
public T getA( ) { }
public void setA (T t) { }
}
3.1使用1泛型来解决Point 点类的安全问题
package demo01;
public class Test01 {
public static void main(String[] args) {
//整型坐标
Point<Integer> p1 = new Point<>(15, 25);
//小数坐标
Point<Double> p2 = new Point<>(25.3, 26.7);
//字符串类型
Point<String> p3 = new Point<>("东经1500度", "北纬35度");
String x = p3.getX();
Integer x1 = p1.getX();//不会出现数据类型安全问题
//注意:泛型的类型必须指定为引用类型 不能使用基本类型
//基本类型:byte short int long float double boolean char
/*在创建泛型类对象时没有指定泛型:---就是 Object类型
Point p4 = new Point(2, 36);
Object x2 = p4.getX();*/
}
}
定义一个类重量:weight---25,25.5,“25克”
4.泛型通配符
在开发中对象的引用传递是最常见的,但是如果在泛型类的操作中,在进行引用传递是泛型类型必须匹配才可以传递,否则是无法传递的
对象的引用传递和值传递
package demo03;
public class Test03 {
public static void main(String[] args) {
Info<Integer> a = new Info<>(15);
Info<String> b = new Info<>("hello");
fun(a);
fun(b);//泛型的引用传递,要求数据类型匹配而且泛型也要匹配
}
public static void fun(Info<?> info){
info.show();
}
}
class Info<T>{
private T var;
public Info(T var){
this.var = var;
}
public void show(){
System.out.println("var----------"+var);
}
public T getVar(){
return var;
}
public void setVar(T var){
this.var = var;
}
}
5.泛型的限制
在引用传递中,在泛型操作中也可以设置一个泛型对象的范围上限和范围下限。范围上限使用extends关键字声明,表示参数化的类型可能是所指定的类型或者是此类型的子类,而范围下限使用super进行声明,表示参数化的类型可能是所指定的类型或者此类型的父亲型。
语法:
public void 方法名(Info<? extends Number> info){
//传递参数的泛型必须是Number 或者Number的子类
}
public void 方法名(Info<? super Number> info){
//传递参数的泛型必须是Number或者Number的父类
}
package demo03;
public class Test03 {
public static void main(String[] args) {
Info<Integer> a = new Info<>(15);
Info<String> b = new Info<>("hello");
Info<Number> c = new Info<>(25.5);
Info<Object> d = new Info<>(250);
fun(a);
fun(b);//泛型的引用传递,要求数据类型匹配而且泛型也要匹配
fun2(c);
fun3(d);
}
//限定泛型的上限:泛型的限制使用在方法的引用传递中
public static void fun2(Info<? extends Number> info){
info.show();
}
//限定泛型的下限:泛型的限制使用在方法的引用传递中
public static void fun3(Info<? super Number> info){
info.show();
}
//任意的泛型都可以传递过来,使用泛型通配符 . ?
public static void fun(Info<?> info){
info.show();
}
}
class Info<T>{
private T var;
public Info(T var){
this.var = var;
}
public void show(){
System.out.println("var----------"+var);
}
public T getVar(){
return var;
}
public void setVar(T var){
this.var = var;
}
}
6.泛型接口
List<T> ArrayList <E> 1.8 版本
在JDK1.5之后,不仅可以声明泛型类,也可以声明泛型接口,声明泛型接口和声明泛型类的语法类似,也是在接口名称后面加上<T>,
语法:
[ 访问权限 ] interface 接口名称 <泛型标识>{
}
泛型接口的实现类的方式有两种:
1.在创建类时也声明泛型而且该泛型的标识必须和接口的标识一致
2.在类实现泛型接口时,指明该泛型的数据类型
package demo04;
public class Test04 {
}
interface USB<T>{
public void show(T t);
}
//在创建类时,也指定泛型要求必须和接口的泛型标志一致
class Upan<T> implements USB<T>{
@Override
public void show(T t) {
}
}
class Shu implements USB<String>{
@Override
public void show(String s) {
}
}
7.泛型方法
前面记录的所有泛型操作都是将整个类进行泛型化,但同样也可以在类中定义泛型化的方法。泛型方法的定义与其所在的类是否是泛型类是没有任何关系的,所在的类可以是泛型类,也可以不是泛型类
public class Test04 {
public static void main(String[] args) {
Test04 t = new Test04();
String hello = t.fun("hello");
Integer fun = t.fun(15);
}
//泛型方法:<T>在方法的返回值前面多了个泛型标志
public <T> T fun(T t){
System.out.println("结果为:" + t);
return t;
}
}
1.泛型类:public class 类名 <标志,标志...>{ }
2.通配符:?
3.限制泛型类型:?super Number ?extends Number 一般用于引用传递
4.泛型接口:public interface 接口<标志,标志...>{ }
5.泛型方法:public <标志> 返回值 方法名(参数列表) { }
8.注解
8.1什么是注解
注释:注释是给开发人员看的。对你的代码加以解释,程序编译后该注释不可见。
注解:注解给程序看,该注解编译后依然存在
@Controller @RequestMapping() --Spring 程序看的
@Override JVM 虚拟机看。重写特点。方法名要和父类被重写的方法一致,参数列表要一致,返回值要一致。访问修饰符不能小于父类访问修饰。抛出的异常不能大于父类异常。
如果注解不被解析,那么注解就没有任何意义
8.2注解的分类
1.预定义注解:-----JDK自带的一些常用注解
1.@Override:表示方法重写,只要使用了该注解必须符合重写的规则
2.@Deprecated:表示已过时,告诉调用者该方法已过时
3.@SuppressWarnings:表示压制警告
4.@FunctionInterface:函数式接口注解。使用注解表明接口中只能有一个抽象方法
package demo05;
import java.util.Date;
public class Test05 {
public static void main(String[] args) {
Son s = new Son();
s.show();
}
}
class Father{
public void print(){
System.out.println("这是father中的方法");
}
}
class Son extends Father{
@Override //检查该方法重写时是否符合重写规则
public void print(){
System.out.println("这是子类的方法");
}
//@Deprecated //标记该方法过时,在调用该方法有个删除线
public void show(){
}
public void showPrefect(){
}
}
@FunctionInterface接口
package demo05;
public class Test {
public static void main(String[] args) {
}
}
@FunctionalInterface //该接口中有且仅有一个抽象方法 1.8以后
interface Usb{
public void show();
//public void show2(); //报错,只能有一个
}
2.自定义注解:-----我们自己定义的注解
public @Interface 注解名{
//属性
}
package demo06;
public @interface My {
}
@My
class Hello{
@My
public void show(@My int a){
}
@My
public String name;
}
自定义的注解默认对代码没有任务影响,如果想让注解有意义,必须解析该注解。可以结合反射,来解析这些注解
Controller注解是因为Spring框架解析了它, @Override JVM解析了它
Springmvc中常见的注解:
@RestController
@RequestMapping
@ResponseBody
@RequestBody
@RequestParam
2.1自定义注解高级
@GetMaping注解可以有属性值
语法:
@interface 注解名 {
数据类型 属性名();
}
3.元注解:----------注解上使用的注解
使用在注解上的注解就是元注解
@Target:作用:告诉该注解使用的范围 默认所有
@Target(value= {ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
1.TYPE,可以使用在类上
2.FIELD,使用在属性上
3.METHOD,使用方法上
4.PARAMETER,使用在方法参数上
5.CONSTRUCTOR,使用在构造方法上
@Retention:作用:该注解什么时候有效 默认:SOURCE
@Retention(value= RetentionPolicy.SOURCE)
1.SOURCE:源码时有效
2.CLASS:字节码有效
3.RUNTIME:运行时有效
@Documented:作用:在代码生成api文档时是否存在该注解
总结:
1.泛型:---限制类中成员的数据类型
2.定义泛型的格式:
public class 类名 <泛型标志,标志...> {
private 标志 属性;
}
3.创建泛型对象时;需要指定泛型类型,如果没有指定,则认为Object类型
4.泛型通配符:----泛型上限extends和泛型下限super
5.泛型接口---
6.泛型方法 <标志>
7.注解:
【1】预定义注解 @Override @FunctionInterface【检测接口中有且仅有一个抽象方法】
【2】自定义注解 @interface 注解名{ } @注解名
【3】元注解