day14_java泛型,枚举

泛型:

参数化数据类型

作用于
类,方法,构造器,接口

泛型类:

在声明类的后面加上类型参数

好处

语法

类名<类型参数>
类型参数可以是一个也可以是多个,多个用逗号分隔

用一个大写字母表示,一般用 T-type E—element K—key V—value

原生类型:

类型后没有 指定具体的类型参数,这样的类型

叫 原生类型。

泛型的通配符

?是无界通配符,可以匹配任意的引用类型

? extends 上限类型 及其上限类型的子类型

super 可以匹配下限类和下限类的父类

注意

类型参数可以指定上限(上界),

1.但是只能指定上界

2.还可以指定多个上限

3.上限可以是类也可以是接口

4.上限既有类又有接口,要先继承类,后实现接口;类在前,接口在后

类型参数和通配符的区别

1.类型参数 只能指定上限,通配符可以指定上限和下限

2.类型参数可以指定多个上限,通配符只能指定一个

3.类型参数可以作为一个类型,通配符不能表示为一种类型

问题,String是Object的子类,那么Point 是否是Point的子类型

答:不是,参数化类型不能继承

    //用通配符解决
    public void show(Point<String> ps,Point<? extends Object> po){
        po  = ps;
    }

问题:会生成几个泛型类

一个。泛型只是起到在编译时期进行类型检查的作用,并不会生成多个字节码文件

//验证
Point3<Integer> p1 = new Point3();
        System.out.println(p1.getClass());
        Point3<String> p2 = new Point3<>();
        System.out.println(p2.getClass());

//运行结果:
class day21.Point3
class day21.Point3

泛型构造

package day21;

class Point4<T>{
    private T x;
    private T y;

    //泛型构造器
    <E>Point4(E e){
        System.out.println(e);
    }

    public T getX() {
        return x;
    }

    public void setX(T x) {
        this.x = x;
    }

    public T getY() {
        return y;
    }

    public void setY(T y) {
        this.y = y;
    }


}


public class Ex4 {

    public static void main(String[] args) {

        //类型推断:根据串的参数的类型确定E是String
        Point4<Integer> p4 = new Point4<Integer>("Hello");
        Point4<Integer> p6 = new Point4<>("hello");
        //显示指定构造器是String类型,此时不能用菱形语法
        Point4<Integer> p5 = new <String>Point4<Integer>("Hello");

    }

}

泛型方法

package day21;

//普通类
class Point5{

    //泛型方法
    public <T> void f(T t){
        System.out.println(t);
    }


    //<一>
    //public <T extends Number> T ff (T t){

    //<二>
    public <T extends Number> T ff (T t){
        //自动推断
        f("hello");
        //如果显示指定的化,要用对象去调用:this.<String>f("abc");this.<String>f("abc");都是指定了对象
        this.<String>f("abc");
        return t;
    }
}
public class Ex5 {

    public static void main(String[] args) {
        Point5 p5 = new Point5();

        //类型推断:根据参数的类型推断
        p5.f("Hello");

        p5.f(11);


        //<一>
        //显示指定类型参数
        //p5.<String>f("abc");

        //<二>
        p5.<Double>f(11.0);

    }

}

类型擦除

1.参数化类型擦除后为原生类型

point -> point

2.类型参数:使用上界替换

(1)无界类型参数

Point ——> Object

会用Object替换

(2)指定了一个上限的,用此上限类型来替换

Point ——> Base

(3)指定了多个上限的,用第一个上限替换

Point

重写方法

package day21;

interface IA1{

}
interface IB1{

}
class Base1 {
    public void f(Point6<String> p) throws Exception {}
}

class Sub1 extends Base1 {

    //重写了
    @Override
    public void f(Point6<String> p)  throws Exception{
        // TODO Auto-generated method stub
        super.f(p);
    }

}

class Point6<T>{
    private T x;
    private T y;

    public T getX() {
        return x;
    }

    public void setX(T x) {
        this.x = x;
    }

    public T getY() {
        return y;
    }

    public void setY(T y) {
        this.y = y;
    }


}

public class Ex6 {

    public void f(Point6<String> p){}//Point6

    public <T> void f(T p){};//Object

    public <T extends Base1> void f(T p){} //Base1


    public <T extends IA1 & IB1> void f(T p){} //IA1


    public static void main(String[] args) {


    }

}

父类参数擦除后和子类相同

异常范围不能比父类大

泛型接口

package day21;

//泛型接口
interface Info <T>{
    void af(T t);
}

//实现类一:实现接口的时候就指定好用什么类型来替换
class InfoImpl1 implements Info<String>{

    @Override
    public void af(String t) {
        // TODO Auto-generated method stub

    }

}

//实现类二:确定不了类型,等应用再定义:InfoImpl2<String>  info = new InfoImpl2<String> ();
class InfoImpl2<T> implements Info<T>{

    @Override
    public void af(T t) {
        // TODO Auto-generated method stub

    }

}


public class Ex7 {

    public static void main(String[] args) {
        InfoImpl2<String>  info = new InfoImpl2<String> ();

    }

}

比较器 TestCompare

自然排序:按照 Comparable接口的方法CompareTo排序

问题:不想按照现有排序方法进行排序,应该怎么解决

实现Comparator 函数式接口

Comparator Exercise4 和 Comparable的区别 Exercise3

1.Comparable是默认的自然排序方式,Comparator 是我们指定的一种排序方式

2.Comparable的比较代码写在要比较对象的类型的内部,Comparator写在比较类型代码的外部

3.Comparable只能指定一种 默认排序方式,Comparator可以定义多种排序方式

枚举

  1. 底层就是class类
  2. 已经继承了一个类Enum,不能再继承其他的类
  3. 对于一个非抽象的枚举类型,默认是final
  4. 构造器是private的
  5. 不能创建对象,在枚举代码的第一行处
  6. 所有的枚举对象都是 public static final的
  7. 当枚举的类中定义了抽象方法,那么每个对象的匿名内部类方式都必须实现这个抽象方法,并且这个枚举类为abstract的

语法:

enum Color{
    枚举成员;
    方法();
    构造();
}

实例代码

package day21;

import java.util.Scanner;

interface InfoNew{
    void af();//抽象方法
}

//可以实现接口
enum Color implements InfoNew{
    //在这里调用构造器
    RED(1,"红色"){


        @Override
        public void af() {
            System.out.println("红色的实现接口");

        }

        @Override
        void f() {
            System.out.println("红色的实现抽象类");

        }


    },GREEN(2,"绿色"){

        @Override
        public void af() {
            System.out.println("绿色的实现接口");

        }

        @Override
        void f() {
            System.out.println("绿色的实现抽象类");

        }


    }, BLUE(3,"蓝色"){

        @Override
        public void af() {
            System.out.println("蓝色的实现接口");

        }

        @Override
        void f() {
            System.out.println("绿色的实现抽象类");         
        }   
    };



    //成员变量
    private int no;
    private String name;


    //构造器  是private的,在这里写没必要
    private Color(int no, String name) {
        this.no = no;
        this.name = name;
    }

    public int getNo() {
        return no;
    }
    public void setNo(int no) {
        this.no = no;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    //自定义方法
    public void show(){
        System.out.println("show");
    }

    //重写
    @Override
    public String toString() {
        return no + name;
    }
    //定义抽象方法
    abstract void f();




}
public class Ex8 {

    public static void main(String[] args) {
        //重写了Stringto
        System.out.println(Color.RED);
        //定义了构造器
        System.out.println(Color.RED.getName() +","+ Color.RED.getNo());
        System.out.println(Color.BLUE.getName() +","+ Color.BLUE.getNo());
        System.out.println(Color.GREEN.getName() +","+ Color.GREEN.getNo());

        //定义成员变量
/*      Color.RED.no = 11;
        Color.RED.name = "红色";
        System.out.println(Color.RED.name);
        System.out.println(Color.RED.no);

        */
        //私有成员变量
        Color.RED.setNo(22);
        Color.RED.setName("红色");
        System.out.println(Color.RED.getName() +"," +Color.RED.getNo());

        //每一个枚举成员都可以调用自定义方法
        Color.BLUE.show();

        //-----------------------------------
/*      System.out.println(Color.RED);
        System.out.println(Color.GREEN);
        System.out.println(Color.BLUE);

        //遍历
        for (Color c : Color.values()){
            System.out.println(c.name());
            //获得枚举类型的编号
            System.out.println(c.ordinal());
        }

        //-----------Switch------------------
        Scanner input = new Scanner(System.in);
        System.out.println("输入颜色");
        String str = input.next();
        //字符串转换为枚举Color类型
        Color c = Color.valueOf(str);
        switch (c){
        case RED:
            System.out.println("是红色");
            break;
        case GREEN:
            System.out.println("是绿色");
            break;
        case BLUE:
            System.out.println("是蓝色");
            break;
        }*/

    }

}

猜你喜欢

转载自blog.csdn.net/qq_24135817/article/details/80455460