通过《码出高效:JAVA开发手册》p164-168页学到了和博客园https://www.cnblogs.com/coprince/p/8603492.html以下知识点:
泛型在java中有很重要的地位,在面向对象编程以及各种设计模式都有广泛的应用!
***1.***泛型即“参数化类型”,一提到参数我们都能想到定义一个方法时括号里的参数是形参,当我们调用此方法时,在括号里面写入的就是实参。例如:
//定义一个方法
void show( int a){
Sysotem.out.println(“我想变得优秀!"+"+"+a);
}
此时在show方法里面,a代表形参,int是参数类型,指定a转入的必须是int类型!
当我们调用方法时填入括号里面的就是实参了!例如:
Person p=new Person();
p.show(1);
此时show()方法括号里面的1就是实际参数,指的就是具体的值。
泛型的本质是是为了参数化类型(通过泛型指定不同的类型来控制形参具体限制的类型)操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
2.
// 第一段 泛型出现之前:集合的定义方式
List a1= new ArrayList();
a1.add(new Object());
a1.add(new Integer(111));
a1.add(new String(“hello ala l”) );
/**
* 第一段说明在没有泛型之前,随便往里面添加什么类型的值都是可以的
* 但是如果你要将这个list转换为某种类型那么就会出现类转换异常ClassCastException
*例如下面的例子:
*/
String inta=(String)a1;
// Cannot cast from List to String 原意是:list不能转换为String
// 第二段 把a1引用赋值给a2 注意a1与a2的区别是a2增加了泛型限制
List a2 = a1 ;
a2.add(new Object ());
a2.add(new Integer( 222 ));
a2.add(new String ("hello a2a2 "));
List,即原始类型,其引用变量可以接受任何对应List的参数化类型, 包括List<?>,并且可以添加任意类型的元素。但其缺点在于不安全性、不便利性、不表述性(不应该使用原生类型的原因)。
List,即实际类型参数为Object的参数化类型,其引用变量可以接受List,可以添加元素,但不能接受除了其本身外的任何参数化类型(泛型的子类型化原则)。
3.
//第一段:声明第三个依次继承的集合:Object>动物>猫>加菲猫 三个泛型集合可以理解为三个不同的笼子
List<Animal> animal = new ArrayList<Animal>(); //动物
List<Cat> cat = new ArrayList<Cat>(); //猫
List<Garfield> garfield = new ArrayList<Garfield>(); //加菲猫
<? extends T>可以赋值给任何T及T子类的集合 ,上界为T, 取出来的类型带有
泛型限制 ,向上强制转型为T. null 可以表示任何类型,所以除 null 外,任何元素都
不得添加进<? extends T> 集合内。代码如下:
//第二段:测试赋值操作 以Cat为核心,因为它既有子类又有父类
//下行编译出错。只能赋值Cat或Cat子类集合
List<? extends Cat> extendsCatFromAnimal = animal;
List<? extends Cat> extendsCatFromCat = cat;
List<? extends Cat> extendsCatFromGarfield = garfield;
//第三段:测试add方法
//下面三行中所有的<? extends T>都无法进行add操作,编译出错
extendsCatFromCat.add(new Animal());
extendsCatFromCat.add(new Cat());
extendsCatFromCat.add(new Garfield());
extendsCatFromCat.add(null);//除了null之外,其他元素都不能添加进去
<? super T>可以赋值给任何T及T的父类集合,下界为T。在生活中,投票选
举类似于<? super >的操作。代码如下:
第四阶段
List<? super Cat> superCatFromAnimal = animal;
List<? super Cat> superCatFromCat = cat;
//下行编译出错。只能赋值Cat或着Cat父类集合
List<? super Cat> superCatFromGarfield = garfield;
//下行编译出错。只能添加Cat或者Cat的子类集合。
superCatFromCat.add(new Animal());
superCatFromCat.add(new Cat());
superCatFromCat.add(new Garfield());
https://www.jianshu.com/p/d4c00768d776博客园和https://blog.csdn.net/JIUTIANDEYING/article/details/80159259 CSDN,扩展泛型类,泛型接口,泛型方法以及常见的集合。。
泛型类
把泛型定义在类上
格式:public class 类名<泛型类型1,…>
注意:泛型类型必须是引用类型
代码如下:
// 泛型类:把泛型定义在类上
public class ObjectTool<T> {
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
// 泛型类的测试
public class ObjectToolDemo {
public static void main(String[] args) {
ObjectTool<String> ot = new ObjectTool<String>();
ot.setObj(new String("中国"));
String s = ot.getObj();
System.out.println("姓名是:" + s);
ObjectTool<Integer> ot2 = new ObjectTool<Integer>();
ot2.setObj(new Integer(69));
Integer i = ot2.getObj();
System.out.println("年龄是:" + i);
}
}
输出结果:
姓名是:中国
年龄是:69
泛型方法
把泛型定义在方法上
格式:public <泛型类型> 返回类型 方法名(泛型类型 .)
代码如下:
// 泛型方法:把泛型定义在方法上
public class ObjectTool {
public <T> void show(T t) {
System.out.println(t);
}
}
public class ObjectToolDemo {
public static void main(String[] args) {
// 定义泛型方法后
ObjectTool ot = new ObjectTool();
ot.show("hello");
ot.show(100);
ot.show(true);
}
}
// 这样我们就可以传递任意类型的参数了
泛型接口
把泛型定义在接口上
格式:public interface 接口名<泛型类型1…>
/* * 泛型接口:把泛型定义在接口上 */
public interface Inter<T> {
public abstract void show(T t);
}
扩展集合:
原文:https://blog.csdn.net/zhangqunshuai/article/details/80660974
List , Set, Map都是接口,前两个继承至Collection接口,Map为独立接口
Set下有HashSet,LinkedHashSet,TreeSet
List下有ArrayList,Vector,LinkedList
Map下有Hashtable,LinkedHashMap,HashMap,TreeMap
注意:
- Queue接口与List、Set同一级别,都是继承了Collection接口。
- 看图你会发现,LinkedList既可以实现Queue接口,也可以实现List接口.只不过呢,
- LinkedList实现了Queue接口。Queue接口窄化了对LinkedList的方法的访问权限(即在方法中的参数类型如果是Queue时,就完全只能访问Queue接口所定义的方法了,而不能直接访问 LinkedList的非Queue的方法),以使得只有恰当的方法才可以使用。
- Collection接口:
- 使用Iterator(迭代器)遍历集合
Iterator接口是Collection接口的父接口,因此Collection集合可以直接调用其方法。
Iterator接口也是Java集合框架中的一员,与Collection系列和Map系列不同的是:
Collection系列、Map系列集合主要是用于盛装数据对象的。 Iteration主要是用于遍历Collection中的元素。
— List 有序,可重复
ArrayList
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程不安全,效率高
Vector
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程安全,效率低
LinkedList
优点: 底层数据结构是链表,查询慢,增删快。
缺点: 线程不安全,效率高
—Set 无序,唯一
HashSet
底层数据结构是哈希表。(无序,唯一)
如何来保证元素唯一性?
1.依赖两个方法:hashCode()和equals()
LinkedHashSet
底层数据结构是链表和哈希表。(FIFO插入有序,唯一)
1.由链表保证元素有序
2.由哈希表保证元素唯一
TreeSet
底层数据结构是红黑树。(唯一,有序)
- 如何保证元素排序的呢?
自然排序
比较器排序
2.如何保证元素唯一性的呢?
根据比较的返回值是否是0来决定
Map接口
Map提供了一种映射关系,其中的元素是以键值对(key-value)的形式存储的,能够实现根据key快速查找value;
Map中的键值对以Entry类型的对象实例形式存在;
建(key值)不可重复,value值可以重复,一个value值可以和很多key值形成对应关系,每个建最多只能映射到一个值。
Map支持泛型,形式如:Map<K,V>
Map中使用put(K key,V value)方法添加
Map接口有三个比较重要的实现类,分别是HashMap、TreeMap和HashTable。
TreeMap是有序的,HashMap和HashTable是无序的。
Hashtable的方法是同步的,HashMap的方法不是同步的。这是两者最主要的区别。
JAVA集合中Comparable与Comparator区别。
Comparator在汉语中的意思是 比较器 ,Comparable在汉语中的意思是 可比的
集合中的元素在进行比较时,都会调用compareTo()方法,该方法就是Comparable接口中的定义,因此要想对集合中元素进行排序,就必须实现Comparable的接口。
代码如下:
public class Student implements Comparable<Student>{
private String name;
private int age;
public Student(){
super();
}
public Student (String name,int age){
this.name=name;
this.age=age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
public String setName(String ename){
this.name=ename;
return name;
}
public int setAge(int ages){
this.age=ages;
return age;
}
public int compareTo(Student s){
int num=this.name.length()-s.name.length();
int num2=num==0?this.name.compareTo(s.name):num;
int num3=num2==0?this.age-s.age:num2;
return num3;
}
@Override
public String toString() {
return "student [name=" + name + ", age=" + age + "]";
}
}
//测试方法
public class Test {
public static void main(String[] args){
TreeSet<Student> s=new TreeSet<Student>();
s.add(new Student("SDFGU",32));
s.add(new Student("WRTYU",23));
s.add(new Student("RTYUS",32));
s.add(new Student("WETWS",23));
s.add(new Student("SDFGU",32));
s.add(new Student("WRTYU",33));
s.add(new Student("QAWSER",32));
s.add(new Student("W3ERTYUI",23));
Iterator<Student> i=s.iterator();
while(i.hasNext()){
System.out.println(i.next());
}
}
}
Student类实现了Comparable接口中的compareTo()方法。在compareTo()方法中,首先对字符串长度进行比较,根据比较结果返回-1或1,或当长度相同时,再对name值进行比较,最后,对age进行比较。因此,可以看出学生首先按照name的长度排序,name的长度相同时会按照字母表的顺序,最后按照age排序。