泛型--方法:将泛型参数列表置返回值前(注意格式)

####引入

关于泛型这篇博客讲的还可以:
http://blog.csdn.net/old_memories/article/details/78079422
还有:
《泛型超详细解读(一):泛型基础》http://blog.csdn.net/jeffleo/article/details/52245870
《 泛型超详细解读(二):super和extend》http://blog.csdn.net/jeffleo/article/details/52250948
《Java中的泛型方法》这篇写的还行https://www.cnblogs.com/iyangyuan/archive/2013/04/09/3011274.html

/**
 * Object 可以接受任意类型,因为发生多态
 一个学生的成绩有三种情况:整数,小数,字符串。。一开始无法确定,所以只能用Object接收。
 * @author Administrator
 */
public class Student {
	private Object javase;
	private Object oracle;
	public Student() {
	}	
	
	public Student(Object javase, Object oracle) {
		super();//父类不止一个构造函数时,显示的调用super才有意义
		//子类会默认调用父类的构造函数,这时候显示的调用没什么意义
		this.javase = javase;
		this.oracle = oracle;
	}
	public Object getJavase() {
		return javase;
	}
	public void setJavase(Object javase) {
		this.javase = javase;
	}
	public Object getOracle() {
		return oracle;
	}
	public void setOracle(Object oracle) {
		this.oracle = oracle;
	}
}
/**
 * 获取值:
 * 1、强制类型转换
 * 2、手动类型检查:避免转换错误  java.lang.ClassCastException:这是个运行时异常
 * @author Administrator
 */
public class App {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Object obj = 80;
		//int score =(int)obj; //jdk1.7以后 Object -->integer -->自动拆箱
		int score=(Integer)obj;  //jdk1.6只能这么写
		System.out.println(score);
		
		//(自动装箱,int->integer 再发生多态转成Object) 
		//存入整数 int -->Integer -->Object
		Student stu = new Student(80,90);

		//()stu.getJavase();  可以转,就像上面Object -->integer -->自动拆箱那样
		int javaseScore =(Integer)stu.getJavase();
		String oracleScore =null ;
		if(stu.getOracle() instanceof String){
			oracleScore =(String)stu.getOracle();
		}
		System.out.println("分数为:"+javaseScore+","+oracleScore);
	}
}

####举例
注意是:编译的时候检查类型。
也就意味着,运行期间泛型就不起作用了,所以可以用反射来绕过泛型。

这里写图片描述

1、泛型类:

这里写图片描述

先看看泛型类:

约定俗称就用图上几个字母。。
/**
 * 泛型类:声明时使用泛型
 * 字母:
 * T  Type 表示类型。 
	K V 分别代表键值中的Key Value。 
	E 代表Element。 
 使用时确定类型
 注意:
 1、泛型只能使用引用类型,不能基本类型。。
 2、泛型声明时,字母不能使用在静态属性|静态方法上。。。
 * @author Administrator
 *
 * @param <T>
 */
public class Student<T1,T2> {
	private T1 javaScore;
	private T2 oracleScore;
	
	//泛型声明时,字母不能使用在 静态属性|静态方法上 
	//因为是在使用的时候确定的,静态的则是在编译的时候确定
	//private static T1 test;  -- 这样是不对的
	
	
	public T1 getJavaScore() {
		return javaScore;
	}

	public void setJavaScore(T1 javaScore) {
		this.javaScore = javaScore;
	}

	public T2 getOracleScore() {
		return oracleScore;
	}

	public void setOracleScore(T2 oracleScore) {
		this.oracleScore = oracleScore;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//使用时指定类型(引用类型) 《只能用integer,不能用int》
		Student<String,Integer> stu = new Student<String,Integer> ();
		//1、安全:类型检查。因为这个时候set就只能是字符串了,否则编译报错。它帮你类型检查了。。
		stu.setJavaScore("优秀");
		//2、省心:类型转换。因为,有自动拆箱,和多态。不用你object到integer,再到int了。它一步到位。
		int it =stu.getOracleScore(); //integer -->自动拆箱
	}
}

再看看泛型接口:

/**
 * 接口中 泛型字母只能使用在方法中,不能使用在全局常量中,因为接口的全局常量是static声明的
 */
public interface Comparator<T> {
	//T  a  = 2;    //这种就是错误的,因为接口的变量都是static的。
	void compare(T t);	
}

再看看泛型方法:

这里写图片描述

import java.io.Closeable;
import java.io.IOException;

/**
 * 泛型方法 <> 是在返回类型前面,类型在使用的时候确定
 * 只能访问对象的信息,不能修改信息,因为类型没定。。比如不能执行a.setXX()方法
 * @author Administrator
 *
 */
public class TestMethod {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		test("a");     //T -->String //类型在使用的时候确定
	}
	//泛型方法
	public static <T> void test(T a){	----  修饰符后面,返回值前面。
		//不能执行a.setXX()方法	因为a的类型没定
		System.out.println(a);
	}
	// extends <=(相当于继承)   这里表示T只能是Closeable接口的实现类
	//... 三个点表示可变参数
	//注意,返回值不是T啊,返回值定死了就是void。 泛型表示的是   参数化类型,表示传入的参数的不确定性。。
	//但是返回值也可以指定成泛型,<T> T test(T t){}
	public static <T extends Closeable> void test(T... a){		
		for(T temp:a){
			try {
				if(null!=temp){
					//只能访问对象的信息,不能修改信息
					//close或者打印都可以,但不能修改
					temp.close();  
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

深入自定义泛型:

这里写图片描述
继承泛型:

/**
 * 父类为泛型类
 * 1、属性
 * 2、方法
 * 
 * 要么同时擦除,要么子类大于等于父类的类型,
 * 不能子类擦除,父类泛型   --- 记住这个即可
 * 1、属性类型。随位置而定
 *  父类中,随父类而定
 *  子类中,随子类而定
 * 2、方法重写:
 *  随父类而定
 * 
 * 
 * @author Administrator
 *
 * @param <T>
 */
public abstract class Father<T,T1> {
	T name;
	public abstract void test(T t);  //让子类重写

}
/**
 * 子类声明时(也就是使用的时候),指定具体类型
 * 属性类型为具体类型
 * 方法同理
 */
class Child1 extends Father<String,Integer>{
	String t2;
	@Override
	public void test(String t) {
	}	
}
/**
 * 子类为泛型类 ,类型在使用时确定
 * @author Administrator
 *
 */
class Child2<T1,T,T3> extends Father<T,T1>{
	T1 t2;

	@Override
	public void test(T t) {
		
	}
}
/**
 * 子类为泛型类,父类不指定类型 ,泛型的擦除,使用Object替换
 */
class Child3<T1,T2> extends Father{
	T1 name2;
	@Override
	public void test(Object t) {
		// TODO Auto-generated method stub		
	
	}
}
/**
 * 子类与父类同时擦除,使用Object替换
 */
class Child4 extends Father{
	String name;	
	@Override
	public void test(Object t) {
		
	}
}
/**
 *错误:子类擦除,父类使用泛型。编译就会报错
 //总之:子类不能单独擦除,要么同时擦除,要么父类擦除
class Child5 extends Father<T,T1>{
	String name;	
	@Override
	public void test(T t) {
		
	}
*/

泛型接口:与继承同理

/**
 * 泛型接口:与继承同理
 * 重写方法随父类而定
 *
 * @param <T>
 */
public interface Comparable<T> {
	void compare(T t);
}

//声明子类时,指定具体类型
class Comp implements Comparable<Integer>{

	@Override
	public void compare(Integer t) {
		// TODO Auto-generated method stub
		
	}	
}
//擦除
class Comp1 implements Comparable{

	@Override
	public void compare(Object t) {
		// TODO Auto-generated method stub
		
	}
	 
}
//父类擦除,子类泛型
class Comp2<T> implements Comparable{

	@Override
	public void compare(Object t) {
		// TODO Auto-generated method stub
		
	}
	 
}
//子类泛型>=父类泛型
class Comp3<T> implements Comparable<T>{

	@Override
	public void compare(T t) {
		// TODO Auto-generated method stub
		
	}
	 
}
//父类泛型,子类擦除 错误

这里写图片描述

/**
*泛型的擦除
*1、继承|实现声明 不指定类型
*2、使用时 不指定类型 
*统一Object 对待 
*1、编译器警告 消除使用Object
*2、不完全等同于Object ,编译不会类型检查
 * @author Administrator
 *
 * @param <T>
 */
public class Student<T> {
	private T javaScore;
	private T oracleScore;
	
	//泛型声明时不能使用 静态属性|静态方法上
	//private static T1 test;
	
	public T getJavaScore() {
		return javaScore;
	}

	public void setJavaScore(T javaScore) {
		this.javaScore = javaScore;
	}

	public T getOracleScore() {
		return oracleScore;
	}

	public void setOracleScore(T oracleScore) {
		this.oracleScore = oracleScore;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Student stu1 = new Student(); 
		//消除警告 使用 Object  
		Student<Object> stu = new Student<Object>(); 
		//stu.setJavaScore("af"); //以Object对待
		
		test(stu1); //stu1 相当于Object 但是不完全等同Object
		//擦除,不会类型检查
		//test(stu);
		test1(stu1);
		test1(stu);
		
	}
	
	public static  void test(Student<Integer> a){
		
	}
	public static  void test1(Student<?> a){
		
	}
}

####深入自定义泛型2:
1、泛型没有多态

Fruit.java
public class Fruit {

}
class Apple extends Fruit{
	
}

/**
 * 多态的两种形式
 * @author Administrator
 *
 */
public class FruitApp {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Fruit f =new Apple();
		test(new Apple());
	}
	//形参使用多态 
	public static void test(Fruit f){
		
	}
	//返回类型使用多态
	public static Fruit  test2(){
		return new Apple();
	}
}
//泛型类
public class A<T> {

}

/**
 * 泛型没有多态
 * @author Administrator
 *
 */
public class App {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//A<Fruit> f = new A<Apple>();
		A<Fruit> f =new A<Fruit>();
		//test(new A<Apple>());
	}
	//形参使用多态
	public static void test(A<Fruit> f){
		
	}
	//返回类型使用多态
	public static A<Fruit>  test2(){
		//return (A<Fruit>)(new A<Apple>());
		return null;
	}
}

这里写图片描述

/**
 * 通配符
 * ?表示类型不定,使用时确定类型
 * ?使用:声明类型|声明方法上,不能在声明类或使用时 用
 * ? extends : <= 上限  指定类型 子类或自身
 * ? super :>=下限   指定类型 为自身或父类
 * @author Administrator
 *
 */
public class Student<T> {
	T score;
	
	public static void main(String[] args) {
		Student<?> stu = new Student<String>();  //声明的时候不指定,使用的时候传递类型String
		test(new Student<Integer>());   //使用
		
		test2(new Student<Apple>());
		//test3(new Student<Apple>()); //泛型没有多态		
		
		//test4(new Student<Apple>()); //<
		 stu  = new Student<Fruit>();;
		//test4(stu); //使用时确定类型
		test4(new Student<Object>());
		test4(new Student<Fruit>());
		
	}
	
	public static void test(Student<?> stu){
		
	}
	public static void test3(Student<Fruit> stu){
		
	}
	// <=
	public static void test2(Student<? extends Fruit> stu){
		
	}
	//>=
	public static void test4(Student<? super Fruit> stu){
		
	}
	
}

没有泛型数组:

/**
 * 没有泛型数组,那容器怎么办,用下面的方法变量保留。JDK源码ArrayList也是这么写的
 * 声明可以使用,但是创建失败
 * @author Administrator
 *
 */
public class Array {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Integer[]  arr = new Integer[4]; 
		//Student<String>[] arr2 = new Student<String>[10];
		Student<?>[] arr2 = new Student[10];
		
		MyArrayList<String> strList =new MyArrayList<String>();
		strList.add(0, "a");
		String elem =strList.getElem(0);
		System.out.println(elem);
	}

}
class MyArrayList<E>{
	//E[] cap =new E[10]; 没有泛型数组:因为这个时候类型不定,无法在内存中开辟空间
	Object[] cap = new Object[10];
	
	public void add(int idx,E e){
		cap[idx] =e;
	}
	
	@SuppressWarnings("unchecked")
	public E[] getAll(){
		return (E[]) cap;
	}
	@SuppressWarnings("unchecked")
	public E getElem(int idx){
		return (E) cap[idx];
	}
}

JDK1.7泛型的改进:

/**
 * 1.7中使用泛型,声明一次类型即可
 * 在使用|创建时不用指定类型
 * @author Administrator
 *
 */
public class Test7 {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		List<String>  arrList= new ArrayList<String>();
		//List<String>  arrList2= new ArrayList<>();
	}
}
package com.zte.sdno.services.wandriver.amx;

import com.zte.sdno.model.fc.model.FCIpsecTunnel;
import com.zte.sdno.services.RestService;
import com.zte.sdno.services.RetroifitService;
import com.zte.sdno.services.hmf.HmfService;
import com.zte.sdno.services.wandriver.amx.interfaces.Ipsec;
import com.zte.sdno.utils.enums.FuncName;
import com.zte.sdno.utils.enums.ModuleName;
import com.zte.ums.zenap.hk2.i18n.I18nException;
import org.jvnet.hk2.annotations.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import retrofit2.Call;
import retrofit2.Retrofit;

import javax.inject.Inject;

/**.
 * IPSEC 隧道接口
 *
 * @author 10225631
 * @Time 2017/8/25 10:21
 */
@Service
public class IpsecService {

    private static final Logger LOGGER = LoggerFactory.getLogger(IpsecService.class);

    @Inject
    private HmfService hmfService;

    @Inject
    private RestService restService;

    @Inject
    private RetroifitService retroifitService;

    /**.
     * 创建 ipsec隧道
     * @param controllerId 控制器Id
     * @param fcIpsecTunnel dirver 南向接口参数
     */
    public void createIpsec(String controllerId, FCIpsecTunnel fcIpsecTunnel) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("create Ipsec begin, input is: " + fcIpsecTunnel);
        }
        Ipsec ipsec = createService(controllerId, Ipsec.class);

        Call<Void> call = ipsec.create(controllerId, fcIpsecTunnel);
        restService.callRequest(call, FuncName.CREATE_IPSEC, ModuleName.WAN_DRIVER, controllerId);

    }

    /**.
     * 更新 IPSEC 隧道
     * @param controllerId 控制器Id
     * @param fcIpsecTunnel dirver 南向接口参数
     */
    public void updateIpsec(String controllerId, FCIpsecTunnel fcIpsecTunnel) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("update Ipsec begin, input is: " + fcIpsecTunnel);
        }
        Ipsec ipsec = createService(controllerId, Ipsec.class);

        Call<Void> call = ipsec.update(controllerId, fcIpsecTunnel);
        restService.callRequest(call, FuncName.UPDATE_IPSEC, ModuleName.WAN_DRIVER, controllerId);
    }

    /**.
     * 删除 IPSEC 隧道
     * @param controllerId 控制器Id
     * @param fcIpsecTunnel dirver 南向接口参数
     */
    public void deleteIpsec(String controllerId, FCIpsecTunnel fcIpsecTunnel) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("delete Ipsec begin, input is: " + fcIpsecTunnel);
        }
        Ipsec ipsec = createService(controllerId, Ipsec.class);

        Call<Void> call = ipsec.delete(controllerId, fcIpsecTunnel);
        restService.callRequest(call, FuncName.DELETE_IPSEC, ModuleName.WAN_DRIVER, controllerId);
    }

    /**.
     * 创建服务类
     */
    private <T> T createService(String controllerId, Class<T> clazz) throws I18nException {
        Retrofit retrofit = retroifitService.initRetrofit(hmfService.getAdapterUrl(controllerId));
        return retrofit.create(clazz);
    }
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值