没事,写一个关于泛型使用的总结,泛型相信大家都不陌生,学过javase的人都知道,泛型一般在框架中用的比较多,平时还是用的比较少的,今天就 总结下泛型怎么使用,
为什么jdk1.5要引入泛型?
先看段代码:
package com.generic;
import java.util.ArrayList;
import java.util.Iterator;
public class Demo1 {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add("刘德华");
arrayList.add("王祖贤");
arrayList.add(100);
Iterator iterator = arrayList.iterator();
while(iterator.hasNext()){
String result = (String) iterator.next();//这里会报错
System.out.println(result);
}
}
}
比如上面的集合 我没有使用泛型,如果要遍历的话 我还要强转,而且我一不小心往集合中放了一个Integer类型进去,就容易报错,也许你会说 怎么可能自己会注意的,但是你做项目,而且忙起来那记得这么多,而且报错还是在运行期间报错,
更是致命,我们最好让错误发生在编译时间,这样程序员就可以修复这个错误,
所以总结起来引入泛型好处就是:减少了强转,增加了程序员的安全性,也方便了很多
那么泛型一般可以作用于:类,方法,接口上
泛型作用于类上就叫泛型类:先讲讲泛型类的使用
泛型类的使用
语法格式:public class 类名<泛型类型1,…> 注意:泛型类型必须是引用类型,
写个demo玩下,
package com.generic;
public class Demo1 {
public static void main(String[] args) {
Person person = new Person("张三");
person.show();
Person person1 = new Person(1111);
person1.show();
}
}
class Person<T>{
private T mt;
public Person(T t) {
super();
this.mt = t;
}
public void show(){
System.out.println(mt);
}
}
只有在你创建对象时才知道泛型是什么类型的,这个特别适合在你抽取某一个功能时,需要父类引入泛型,子类具体传递那个泛型,android中adapter有几个方法 其实用到的也就是getView()方法,其他方法都用不上,而且每次都写在那里,那么这个时候你就写一个抽象的父类,把三个用不上的方法给写上 把getView()写成抽象的方法 因为每个子类实现不一样,这样你数据实体就可以使用泛型来定义,
泛型使用在类上有二个情况,一种是你知道传递什么类型,还有一个情况是你不知道传递什么类型,
知道传递什么类型的情况:
package com.generic;
public class Demo1 {
public static void main(String[] args) {
}
}
abstract class Person<T>{
}
class Man extends Person<String>{
}
在Man这个类中你知道要传递是String类型,如果你Man也不知道传递是什么泛型,可以这么写:
package com.generic;
public class Demo1 {
public static void main(String[] args) {
Man<String> man = new Man<String>();
man.show();
}
}
abstract class Person<T>{
}
class Man<T> extends Person<T>{
public void show(){
System.out.println("您好");
}
}
现在讲下泛型接口的时候:
语法格式:格式:public interface 接口名<泛型类型1…>
package com.generic;
public class Demo1 {
public static void main(String[] args) {
}
}
interface InnerImpl<T>{
public void show();
}
class A implements InnerImpl<String>{
@Override
public void show() {
}
}
泛型类和接口是一样的,在这不多讲,
现在讲下泛型的继承:
有四种情况,保留和不保留父类的泛型
public abstract class Father<T1,T2> { } //不保留泛型 没有类型 类似以Object 类似于Father<Object,Object> class Son4 extends Father{ } //不保留父类的泛型类型,而是具体的类型 class Son3 extends Father<Integer,String>{ } //保留父类部分泛型 class Son2<T2> extends Father<Integer,T2>{ } //全部保留父类部分泛型 class Son1<T1,T2> extends Father<T1,T2>{ }如果父类泛型是一个具体的泛型,那么子类只要按需实现即可,如果父类是泛型,那么子类必须是泛型子类,比如Son1,现在在父类的Father中写一个方法eat
public abstract class Father<T1,T2> { abstract void eat(T2 t); }再来看四个子类是啥样的?
public abstract class Father<T1,T2> { abstract void eat(T2 t); } //不保留泛型 没有类型 类似以Object 类似于Father<Object,Object> class Son4 extends Father{ @Override void eat(Object t) { } } //不保留父类的泛型类型,而是具体的类型 class Son3 extends Father<Integer,String>{ @Override void eat(String t) { } } //保留父类部分泛型 class Son2<T2> extends Father<Integer,T2>{ @Override void eat(T2 t) { } } //全部保留父类部分泛型 class Son1<T1,T2> extends Father<T1,T2>{ @Override void eat(T2 t) { } }总结一句话就是泛型方法中的泛型是根据它父类而定。泛型接口也是和这同理
泛型方法
把泛型定义在方法上
语法格式 : public <泛型类型> 返回类型 方法名(泛型类型 .)泛型接口
package com.generic;
public class Demo1 {
public static void main(String[] args) {
A a = new A();
a.show(0);
a.show("helloworld");
a.show(100);
}
}
class A{
public void show(String str){
System.out.println(str);
}
public void show(int i){
System.out.println(i);
}
public void show(double d){
System.out.println(d);
}
}
比如我在A类中 有这么多show的重载方法,如果我要让show方法接受的形参能根据它传递过来的就打印出来什么,我们就不用写那么多重载的方法了,这个就用泛型方法就可以解决!
package com.generic;
public class Demo1 {
public static void main(String[] args) {
A a = new A();
a.show(0);
a.show("helloworld");
a.show(100);
}
}
class A{
public <T >void show(T t){
System.out.println(t);
}
}
用泛型方法解决上面的 问题,我们知道方法有静态方法,那么静态方法有泛型会怎么办呢?
package com.generic;
public class Demo1 {
public static void main(String[] args) {
A a = new A();
a.show(0);
a.show("helloworld");
a.show(100);
}
}
class A{
public static <T >void show(T t){
System.out.println(t);
}
}
其实是一样的,但是有警告,它会让你直接用A的方式调用这个方法,而不是创建对象去调用方法,那么如果我方法有返回值呢?而且是泛型传递什么我就返回什么.
package com.generic;
public class Demo1 {
public static void main(String[] args) {
String str = A.show("helloword");
int i = A.show(100);
}
}
class A{
public static <T > T show(T t){
return t;
}
}
这样就ok,
泛型还有一个高级的地方就是泛型通配符
泛型通配符<?>
任意类型,如果没有明确,那么就是Object以及任意的Java类了
还是用例子来说明:
package com.generic;
import java.util.ArrayList;
import java.util.List;
public class Demo1 {
public static void main(String[] args) {
List<Object> obj = new ArrayList<Object>();
//下面三个报错是因为泛型如果明确写的时候,前后必须一致
// List<Object> obj1 = new ArrayList<Animal>();
// List<Object> obj2 = new ArrayList<Dog>();
// List<Object> obj3 = new ArrayList<Cat>();
//使用通配符
List<?> obj1 = new ArrayList<Animal>();
List<?> obj2 = new ArrayList<Dog>();
List<?> obj3 = new ArrayList<Cat>();
}
}
class Animal{
}
class Dog extends Animal{
}
class Cat extends Animal{
}
下面使用通配符就可以搞定了,
如果我现在有一个需求就是要求集合能存储的是Animal以及Animal的子类,这个时候就会用到? extends E 这个通配符了,它表示的是向下限定,E及其子类,如果不是E的子类放到集合中就会编译报错:
List<? extends Animal> obj1 = new ArrayList<Animal>();
List<? extends Animal> obj2 = new ArrayList<Dog>();
List<? extends Animal> obj3 = new ArrayList<Cat>();
? extends 表示泛型的上限 比如:
package com.test; /** * Created by Adminis on 2017/11/3. */ public class Fruit { }
package com.test; /** * Created by Adminis on 2017/11/3. */ public class Apple extends Fruit { }
package com.test; /** * Created by Adminis on 2017/11/3. */ public class Iphone8 extends Apple { }
package com.test; /** * Created by Adminis on 2017/11/3. */ public class Pear extends Fruit { }使用:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); List<? extends Fruit> list = new ArrayList<Fruit>(); test(list); setContentView(R.layout.activity_main); userDao = getInstance().getDao(UserDao.class,User.class); } protected void test(List<? extends Fruit> list) { list.add(new Apple()); }你会发现list.add会报错:
这说明? extends 只能读取,而不能添加,这验证也很简单,上面的Iphone8是Apple的子类,而Apple是Fruit的子类,所以你传递进来没啥问题,到时你添加就超过了它的泛型限制了.
而?supper 规定的是一个下限 也就是自身和父类了, 刚好和extends相反,能添加数据,因为 它限制了最大值,