- 泛型类
- 泛型方法
- 静态方法泛型
- 泛型接口
- 泛型限定
泛型:JDK1.5版本以后出现新特性,用于解决安全问题,是一个类型安全机制
好处:
1.将运行时期出现问题ClassCastException,转移到了编译时期。方便于程序员解决问题,让运行事情问题减少,安全。
2.避免强制转换麻烦
泛型格式:
通过<>来定义要操作的引用数据类型。
在使用Java提供的对象中,什么时候写泛型呢?通常在集合框架中很常见,只要见到<>就要定义泛型。当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
Demo1:
java
public static void sop(Object object){
System.out.println(object);
}
public static void main(String[] args) {
//只能存储String类型的字符
ArrayList<String> aList = new ArrayList<String>();
aList.add("aaa");
//用迭代器取出的元素,也需要明确迭代类型
Iterator<String> iterator = aList.iterator();
while (iterator.hasNext()) {
sop(iterator.next());
}
}
Demo2:
java
public class Demo {
public static void sop(Object object){
System.out.println(object);
}
public static void main(String[] args) {
TreeSet<String> treeSet = new TreeSet<String>(new MyCompare());
treeSet.add("ddfv");
treeSet.add("saaa");
treeSet.add("fv");
Iterator<String> iterator = treeSet.iterator();
while (iterator.hasNext()) {
String string = iterator.next();
sop(string);
}
}
}
class MyCompare implements Comparator<String>{
@Override
public int compare(String o1, String o2) {
int num = new Integer(o1.length()).compareTo(new Integer(o2.length()));
if (num == 0) {
return o1.compareTo(o2);
}
return num;
}
}
泛型类
什么时候定义泛型类?当类中要操作的引用类型不确定的时候,早期定义Object来完成,使用Object要进行强转,而现在定义泛型来完成扩展。
java
public class Demo {
public static void sop(Object object){
System.out.println(object);
}
public static void main(String[] args) {
Utils<Work> utils = new Utils<Work>();
utils.setQq(new Work());
//使用泛型类,不需要进行强转
Work uWork = utils.getQq();
/*Tool tool = new Tool();
tool.setObject(new Work());
//需要进行强转
Work work = (Work)tool.getObject();*/
}
}
class Work{ }
class Student{}
//泛型类
class Utils<QQ>{
private QQ qq;
public void setQq(QQ qq) {
this.qq = qq;
}
public QQ getQq() {
return qq;
}
}
//泛型前做法
class Tool{
private Object object;
public void setObject(Object object) {
this.object = object;
}
public Object getObject() {
return object;
}
}
泛型方法
泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了,为了让不同方法可以操作不同的对象,而且类型还不确定,那么可以将泛型定义在方法上。
java
public static void main(String[] args) {
DemoMothd demoMothd = new DemoMothd();
demoMothd.show("hahha");
demoMothd.show(5);
demoMothd.print("aaa");
}
}
class DemoMothd{
//泛型方法
public <T> void show(T t){
System.out.println("show:"+t);
}
public <Q> void print(Q q){
System.out.println("print:"+q);
}
}
同样泛型方法和泛型类也是可以共同存在的
java
public static void main(String[] args) {
DemoMothd<String> demoMothd = new DemoMothd<String>();
demoMothd.show("hahha");
//demoMothd.show(5);这样是不能传int类型,因为DemoMothd的泛型是String,它所属的show方法类型是跟随DemoMothd对象的泛型,而print方法有自己的泛型类型,所以不跟随DemoMothd对象的类型。
demoMothd.print(5);
demoMothd.print("aaa");
}
}
class DemoMothd<T>{
public void show(T t){
System.out.println("show:"+t);
}
public <Q> void print(Q q){
System.out.println("print:"+q);
}
}
打印:
bash
show:hahha
print:5
print:aaa
静态方法泛型
静态方法不可以访问类上定义的泛型。如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。
java
public static void main(String[] args) {
DemoMothd<String> demoMothd = new DemoMothd<String>();
demoMothd.show("hahha");
demoMothd.print(5);
demoMothd.print("aaa");
DemoMothd.method("静态方法泛型");
}
}
class DemoMothd<T>{
public void show(T t){
System.out.println("show:"+t);
}
public <Q> void print(Q q){
System.out.println("print:"+q);
}
//静态先加载后有对象,所以静态方法不可以访问类上定义的泛型
public static <W> void method(W w){
System.out.println("method:"+w);
}
}
打印结果:
bash
show:hahha
print:5
print:aaa
method:静态方法泛型
泛型接口
不是很常见
java
public static void main(String[] args) {
InterImpl impl = new InterImpl();
impl.show("InterImpl");
InterImpl2<Integer> impl2 = new InterImpl2<Integer>();
impl2.show(666);
}
}
//泛型定义在接口上
interface Inter<T>{
void show(T t);
}
class InterImpl implements Inter<String>{
@Override
public void show(String t) {
System.out.println("InterImpl = "+t);
}
}
class InterImpl2<T> implements Inter<T>{
@Override
public void show(T t) {
System.out.println("InterImpl2 =" +t);
}
}
打印:
bash
InterImpl = InterImpl
InterImpl2 =666
泛型限定
?通配符,也可以理解为占位符
? extends E:可以接收E类型或者E的子类型,上限
? super E :可以接收E类型或者E类型的父类型,下限
Demo 1
?通配符,也可以理解为占位符
java
public class Demo {
public static void sop(Object object){
System.out.println(object);
}
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("asddd");
arrayList.add("asddd");
ArrayList<Integer> arrayList2 = new ArrayList<Integer>();
arrayList2.add(3);
arrayList2.add(2);
//proColl方法可以接收ArrayList任意类型对象
proColl(arrayList);
proColl(arrayList2);
}
//?为通配符,不明确对象类型
public static void proColl(ArrayList<?> aList) {
Iterator<?> iterator = aList.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
sop(obj);
}
}
/*也可以定义为静态泛型T,T可以明确对象
public static <T> void proColl2(ArrayList<T> aList) {
Iterator<T> iterator = aList.iterator();
while (iterator.hasNext()) {
T t = iterator.next();
sop(t);
}
}*/
}
Demo 2
? extends E:可以接收E类型或者E的子类型,上限
java
public static void main(String[] args) {
ArrayList<Person1> arrayList = new ArrayList<Person1>();
arrayList.add(new Person1("aaa"));
arrayList.add(new Person1("ddd"));
ArrayList<Student> arrayList2 = new ArrayList<Student>();
arrayList2.add(new Student("stu1"));
arrayList2.add(new Student("stu2"));
proColl2(arrayList);
proColl2(arrayList2);
}
//只打印student子类和Person父类
public static void proColl2(ArrayList<? extends Person1> aList) {
Iterator<? extends Person1> iterator = aList.iterator();
while (iterator.hasNext()) {
Person1 t = iterator.next();
sop(t.getName());
}
}
class Person1{
private String name;
public Person1(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class Student extends Person1{
public Student(String name) {
super(name);
}
}
打印:
bash
aaa
ddd
stu1
stu2
Demo 3
? super E :可以接收E类型或者E类型的父类型,下限
java
//一个Person1父类
class Person1{
private String name;
public Person1(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
//Student 子类
class Student extends Person1{
public Student(String name) {
super(name);
}
}
//Worker 子类
class Worker extends Person1{
public Worker(String name) {
super(name);
}
}
public static void main(String[] args) {
//传入Student比较器
TreeSet<Student> tSet= new TreeSet<Student>(new MyCompare());
tSet.add(new Student("addd1"));
tSet.add(new Student("addd2"));
tSet.add(new Student("addd3"));
Iterator<Student> iterator = tSet.iterator();
while (iterator.hasNext()) {
Student t = iterator.next();
sop(t.getName());
}
//Worker传入比较器
TreeSet<Worker> tSetWork= new TreeSet<Worker>(new MyCompare());
tSetWork.add(new Worker("Work1"));
tSetWork.add(new Worker("Work2"));
tSetWork.add(new Worker("Work3"));
Iterator<Worker> iteratorWork = tSetWork.iterator();
while (iteratorWork.hasNext()) {
Worker t = iteratorWork.next();
sop(t.getName());
}
}
//为什么这里传入的是父类类型,因为TreeSet接收的是<? super E>,如果传入Student 那么这个比较器只能被TreeSet<Student>类型用,如何传入Worker类,只能被TreeSet<Worker>用,而Person1是既可以被TreeSet<Student>用也可以被TreeSet<Worker>用,这样就很方便了。
class MyCompare implements Comparator<Person1>{
@Override
public int compare(Person1 o1, Person1 o2) {
return o1.getName().compareTo(o2.getName());
}
}
源码展示:
java
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator));
}
打印结果:
bash
addd1
addd2
addd3
Work1
Work2
Work3