泛型
泛型主要是用于约束类,接口和方法的,主要是以传参的形式来替换所有的类型
使用场景:在申明或者定义集合的时候,不知道具体的数据类型的时候,就是用泛型
泛型只能够是引用数据类型,不能是基本数据类型
泛型的语法:
public <T> int getAge(){}
//<一些大写的字母>
常规的一些泛型的大写字母<E> <W> <K> <V> <T>...
//泛型在jdk1.7之后
ArrayList<String> list = new ArrayList<>();
//是由前面的泛型推出后面的泛型
//在jdk1.7之前
ArrayList<String> list = new ArrayList<String>();
//前面泛型必须是一样
没有泛型:
好处:可以存任意的类型(默认的是Object)
坏处:不安全,容易出错,强制类型转换错误 java.lang.ClassCastException
有泛型的:
好处:把运行时的错误,提前到编译的错误 2.避免强制类型转换
坏处: 只能够存一种数据类型
- 使用泛型来修饰类
public class Test<T>{
...
}
修饰类的语法:
访问修饰符 class 类名{}
注意点:
1.在申明这个类的时候,是不能够确定具体的类型
2.在实例化肯定要确定其泛型
3.类上的泛型,整个类都可以使用
- 使用泛型来修饰方法
public <T> void show(){
...
}
//在访问修饰符有返回值类型的前面加上泛型
修饰方法的语法:
访问修饰符 <泛型1,泛型2>返回值类型 方法名(参数,(可以使用泛型)){}
- 静态的方法
public static <T> void show(){
...
}
//不能使用类的泛型,只能在方法前申明
4.使用泛型来修饰接口
public interface Test<T>{
...
}
修饰接口的语法
访问修饰符 interfance 接口的名称<泛型>
一般是给实现类来使用: 实现类有两种情况
1.实现类具体确定其泛型的类型
public interface MyIter<T> {
void show(T s);
}
public class Test implements MyIter<String> { //确定接口类型
@Override
public void show(String s) {
System.out.println(s);
}
}
2.实现类也不确定其泛型,只有实例化的时候才能确定
public class Test<T> implements MyIter<T>{ //不确定接口类型
@Override
public void show(T s) {
System.out.println(s);
}
}
4.泛型的通配符 ? , 表示任意的泛型,也就是确定是什么泛型的时候使用
注意点:
1.一般是用于方法的参数里
2.泛型是没有继承的概念
3.在实例化的时候,不能给通配符,必须确定其泛型了
public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
show(list);
show01(list);
show02(list);
}
public static void show(Collection<?> col){ //<?>可以是任何类型
Iterator<?> iter = col.iterator();
while(iter.hasNext()){
System.out.print(iter.next()+" ");
}
}
public static void show01(Collection<? extends String> col){ //<?>可以是String或者String的子类
Iterator<?> iter = col.iterator();
while(iter.hasNext()){
System.out.print(iter.next()+" ");
}
}
public static void show02(Collection<? super String> col){ //<?>可以是String或者是String的父类
Iterator<?> iter = col.iterator();
while(iter.hasNext()){
System.out.print(iter.next()+" ");
}
}
}
<? extends E>
表示 只能是E泛型本身或者是其子类
<? super E>
表示只能够是E泛型的本身,或者是其父类
Set
集合:
- 是Collection 的子接口
- 不能存重复的元素
- 无序(没有索引),不能使用普通的for循环
HashSet: 子类的特点:
- 使用的是哈希表结构来进行存储
- 无序 (没有索引)
- 不能存相同的元素.,不能重复
- 类允许null元素
set集合有几种遍历方式:
- 没有加泛型转换成数组
- 加了泛型转换成数组
- 使用迭代器
- 使用增强for循环
public class Test {
public static void main(String[] args) {
Set<News> set = new HashSet<>();
set.add(new News("news01","some01"));
set.add(new News("news02","some02"));
show01(set);
show02(set);
show03(set);
show04(set);
}
public static void show01(Set set){ //没有加泛型转换成数组
Object[] objs = set.toArray();
for(int i=0;i<objs.length;i++){
System.out.println(objs[i].toString());
}
}
public static void show04(Set<News> set){//加了泛型转换成数组
News[] objs = new News[set.size()];
set.toArray(objs);
for(int i=0;i<objs.length;i++){
System.out.println(objs[i].toString());
}
}
public static<T> void show02(Set<T> set){//使用增强for循环
for(T obj:set){
System.out.println(obj.toString());
}
}
public static<T> void show03(Set<T> set){//使用迭代器
Iterator<T> iter = set.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
}
}
hashSet集合存入数据的时候,是如何保证没有重复的数据
其实就是通过 hashCode()和equals()判断两个对象是否一样:
- hashCode值不一样,存储
- hashCode值一样,equals()进行比较,有相等的不存储,没有相等的进行存储
TreeSet 可以进行排序:自然排序: 默认的字符串 ,遵循与字典表进行排序
引用数据类型(自己新建的类),如果使用TreeSet来进行存储,都要实现Comparable接口,重写其方法compareTo()方法,自定义规则去比较
public class Test implements Comparable{
public Integer value;
public Test(int value) {
this.value = value;
}
@Override
public int compareTo(Object o) { //实现compareTo接口
Test t = (Test)o;
return value.compareTo(t.value);
}
@Override
public String toString() {
return "Test{" +
"value=" + value +
'}';
}
}