Java 学习笔记 Day014

来源:互联网 发布:彩八仙计划软件 编辑:程序博客网 时间:2024/05/06 11:04

泛型

在某些情况下,在定义类型的时候不方便限定类型中需要使用的数据(对象)的类型。
泛型类:在类名后面添加了类型参数声明部分。泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。

//filename:Genericity01.java//@author Gonsonpublic class Genericity01 {    public static void main(String[] args) {        //对Human类进行实例化时,要将泛型具体到某一个类型(从广泛 到 具体 )        //所以当不方便限定类型中需要使用的数据(对象)的类型时,通过泛型可以接收不同类型的参数        Human<Man> humanM = new Human<>();        humanM.whatSex(new Man());        //当实例化带有泛型的类时,如果没有声明 泛型标志 对应的类型,那么默认会声明是Object类。        //虽然在eclipse中会提示告警“泛型类型的引用应参数化”,但以下声明是可以编译和执行的        Human humanW = new Human();        humanW.whatSex(new Woman());        //所以在一些情况下,泛型的功能与 Object 类的功能类似。        HumanObject humanO = new HumanObject();        humanO.whatSex(new Man());        //泛型可以生产变量,可以做方法的返回值。        //<T> T不能创建对象,因为不知道T的构造方法怎么样的。        HumanB<Man, Woman> humanMW = new HumanB<>();        humanMW.whatSexM(new Man());        humanMW.whatSexW(new Woman());          }}//定义一个带有泛型的  人    类class Human<T>{    public void whatSex(T t){        System.out.println(t);    }}class HumanObject{    public void whatSex(Object o){        System.out.println(o);    }}//泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开class HumanB<M, W>{    public void whatSexM(M t){        System.out.println(t);    }    public void whatSexW(W t){        System.out.println(t);    }}//男人class Man{    @Override    public String toString() {        return "male";    }}//女人class Woman{    @Override    public String toString() {        return "female";    }}/*执行结果malefemalemalemalefemale*/

泛型方法:该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。

public class Genericity02 {    public static void main(String[] args) {        Integer[] a = {23,54,54,12,32,59};        System.out.println(genTest(a));    }    //声明一个带泛型的方法,返回类型也可以根据泛型而定。    public static <E> E genTest(E[] ele){        for (E e : ele) {            System.out.print(e + "  ");        }        System.out.println("\n****");        return ele[0];    }}

泛型统配符:?

public class Genericity03 {    public static void main(String[] args) {        callDog(new Dog<String>());    }    //当通过带泛型的类来实例化一个对象时,而类又不确定 可以用通配符来代替    public static void callDog(Dog<?> d){        System.out.println("test");    }}class Dog<T> {    //一个带泛型的类}

泛型的上限:要求是某个类的或其子类,不能是其父类。

//通配符? 的上限是B, 只能代表B类或 B的子类public static void callDog(A<? extends B> c){    System.out.println("test");}

泛型的下限:要求是某个类的或其父类,不能是其子类。

//通配符? 的上限是B, 只能代表B类或 B的父类public static void callDog(A<? super B> c){    System.out.println("test");}

高级API之克隆(Cloneable)

每个类都继承了Object 的clone 方法,但是Object.clone这个公共方法是受保护的,如果没有实现Cloneable 接口的实例上调用 Object 的 clone 方法,则会导致抛出 CloneNotSupportedException 异常。 当实现了Cloneable 接口,便可以 Object.clone() 方法可以合法地对该类实例进行按字段复制。

public class TheMain {    public static void main(String[] args) throws CloneNotSupportedException {        Dog d1 = new Dog("DaBan", 4);        //把d1  赋值给 d2 其实就是d1,d2指向了同一个对象        Dog d2 = d1;         //clone 就是把原来的 对象完整的克隆一份,是一个新的对象        Dog d3 = (Dog) d1.clone();        //d2 setName 对象的改变也影响到了d1        d2.setName("XiaoBan");        //d3 setName 只是改变自己        d3.setName("WangCai");        System.out.println(d1);        System.out.println(d2);        System.out.println(d3);    }}class Dog implements Cloneable{    private String name;    private int age;    public Dog(String name, int age) {        super();        this.name = name;        this.age = age;    }    public void setName(String name) {        this.name = name;    }    public void setAge(int age) {        this.age = age;    }    @Override    public String toString() {        return "Name=" + name + ", Age=" + age;    }    @Override    protected Object clone() throws CloneNotSupportedException {        return super.clone();    }}

上面的例子是浅克隆,如果类属性用有 引用类型对象 的时候,clone 只能clone引用的对象的指针(引用),不能克隆引用的对象。这是时候就要进行深克隆(多层克隆)。

class Person implements Cloneable{    private String name;    private Dog dd;    public Person(String name, Dog dd) {        super();        this.name = name;        this.dd = dd;    }    public void setName(String name) {        this.name = name;    }    public void setDd(Dog dd) {        this.dd = dd;    }    @Override    public String toString() {        return "PersonName:" + name + "\t\t DogInfo: " + dd.toString();    }    @Override    protected Object clone() throws CloneNotSupportedException {        //先把自己克隆给temp        Person temp = (Person) super.clone();        //把person的Dog 克隆。        //如果没有这操作,只是浅克隆,原来person的dog 和克隆的dog 是两个引用同一个对象,        temp.dd = (Dog) this.dd.clone();        return temp;    }}

高级API之比较(Comparable)

此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。
实现此接口的对象列表(和数组)可以通过 Collections.sort(和 Arrays.sort)进行自动排序。实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。

//这个Student类实现了Comparable 接口class Student implements Comparable<Student>{    int Score; //有一个Score 属性    //覆写 compareTo比较器    @Override    public int compareTo(Student o) {        //根据情况返回 1 / -1 / 0        if (this.Score > o.getScore()) return 1;        else if (this.Score < o.getScore()) return -1;        else return 0;    }    public int getScore() {        return Score;    }}

Comparable 接口应用在 对象数组的比较,可以实现排序。
在Arrays类有sort方法,就是根据比较器来实现的。Array.sort()根据指定比较器产生的顺序对指定对象数组进行排序。数组中的所有元素都必须是通过指定比较器可相互比较的(也就是说,对于数组中的任何 e1 和 e2 元素而言,c.compare(e1, e2) 不得抛出 ClassCastException)。

StringBuffer

Stringbuffer, StringBuilder
Java 中string 对象是只读的,某些情况在处理多个的string对象导致内存浪费、
因而引入Stringbuffer, StringBuilder来动态处理字符串,除了类的名字不一样其他都一样
stringBuffer 是异步的,速度底线程安全,
stringBuilder 是同步的,速度快,线程不安全。

StringBuffer 和 StringBuilder 的方法大致相同,在处理字符串上功能比String优,具体通过JavaAPI熟悉使用。

Collection

(集合:集合是类型的对象的一种引用存储形式)
Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 Set 和 List)实现。此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。
Collection接口常用的实现类有: , HashSet, TreeSet, ArrayList, LinkedList, Vector,Arrays, AbstractCollection,HashMap,TreeMap 等等
Arrays:此类包含用来操作数组(比如排序和搜索)的各种方法。此类还包含一个允许将数组作为列表来查看的静态工厂。

ArrayList: List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。每个 ArrayList 实例都有一个容量。该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向 ArrayList 中不断添加元素,其容量也自动增长。

HashSet:此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。

TreeSet:基于 TreeMap 的 NavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。

TreeMap:基于红黑树(Red-Black tree)的 NavigableMap 实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。

HashMap:基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

0 0
原创粉丝点击