黑马程序员-泛型延伸

------- android培训java培训、期待与您交流! ----------
泛型:编译器编译带类型说明的集合就是去掉类型信息。
ArrayList<E>
整个称为ArrayList的泛型类型
E称为类型变量或类型参数
ArrayList<Integer>称为参数化的类型
Integer称为类型参数的实例或实际类型参数,只有对象的引用类型才能作为泛型的实际类型参数。
读法:<>念type of
ArrayList 原始类型


参数化类型与原始类型的兼容性
Collection<String> = new Vector();
Collection c = new Vector<String>();
上面两种都是可以的,虽然编译器会警告


参数化类型不考虑类型参数的继承关系:
Vector<String> v = new Vector<Object>();//错误
Vector<Object> v = new Vector<String>();//也错误


在创建数组实例时,数组的元素不能使用参数化的类型:
Vector<Integer> vectorList[] = new Vector<Integer>[10];//错误


Vector v1 = new Vector<String>();//可以
Vector<Object> = v1; //这个编译也能通过,编译器是严格按照一行一行的语法来判断的。


泛型中的 ?通配符
public static void printCollection(Collection<?> cols)
{
	for(Object obj:cols)
	{
		System.out.println(obj);
	}
	//cols.add("String");//错误,因为不知道到未来匹配的一定就是String
	cols.size();//ok,此方法与类型参数无关
	cols = new HashSet<Date>();
}

通配符上边界:? extends Number
通配符下边界:? super Integer
并且可以用&限定多个边界。



java语言中的泛型基本上是在编译器中实现的,用于编译器执行类型检查和类型判断,
在生成字节码后会删除,这种称之为擦除。


private static <T> void swap(T[] a,int i,int j){
T temp = a[i];
a[i] = a[j];
a[j] = temp;
}
只有引用类型才能作为泛型方法的实际参数,swap(new int[3],3,5)会报错。


异常采用泛型:
	private static <T extends Exception> sayHello()throws T
	{
		try
		{
		}catch (Exception e){
			throw (T)e;
		}
}



把Object类对象转成其他类对象:
private static <T> T autoConvert(Object obj)
{
return (T)obj;
}


泛型方法的类型参数的类型推断:根据调用泛型方法时实际传递的参数类型或返回值的类型来推断:
1.参数列表中只有一处被调用,直接根据调用方法时传递的参数类型或返回值来决定
2.多处对应同一种类型,可以凭感觉推断出来
3.多处对应不同类型,且没有返回值,这时去多个参数的最大交集类型
4.多处对应不同类型,且有返回值类型,优先考虑返回值类型



dao:data access object-->crud
定义泛型类型:如果类的实例对象中的多处用到泛型,可以把泛型定义在类上。
当一个变量被声明是泛型时,只能被实例变量和方法调用(还有内嵌类型),而不能被静态
变量和 静态方法调用。因为静态成员是被所有参数化的类所共享的,所以静态可以自己单独
定义泛型变量。



通过反射获得泛型的实际类型参数: ******
Vector<Date> v = new Vector<Date>();//通过v是无法获得其泛型的类型
public static void applyVector(Vector<Date> v)//不过可以通过应用该变量的方法来返回该方法的参数的泛型类型。
	{}
public static void main(String[] args)
{
	Method applyMethod = GenericTest.class.getMethod("applyVector",Vector.class);
	Type[] types = applyMethod.getGenericParameterTypes();
	ParameterizedType pType = (ParameterizedType)types[0];
	System.out.println(pType.getRawType());
	System.out.println(pType.getActualTypeArguments()[0]);//返回此类的实际参数类型的Type对象的数组,因为参数类型可能有多个
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java是Java 5引入的新特性,可以提高代码的可读性和安全性,降低代码的耦合度。是将类参数化,实现代码的通用性。 一、的基本语法 在声明类、接口、方法时可以使用的声明方式为在类名、接口名、方法名后面加上尖括号<>,括号中可以声明一个或多个类参数,多个类参数之间用逗号隔开。例如: ```java public class GenericClass<T> { private T data; public T getData() { return data; } public void setData(T data) { this.data = data; } } public interface GenericInterface<T> { T getData(); void setData(T data); } public <T> void genericMethod(T data) { System.out.println(data); } ``` 其中,`GenericClass`是一个类,`GenericInterface`是一个接口,`genericMethod`是一个方法。在这些声明中,`<T>`就是类参数,可以用任何字母代替。 二、的使用 1. 类的使用 在使用类时,需要在类名后面加上尖括号<>,并在括号中指定具体的类参数。例如: ```java GenericClass<String> gc = new GenericClass<>(); gc.setData("Hello World"); String data = gc.getData(); ``` 在这个例子中,`GenericClass`被声明为一个类,`<String>`指定了具体的类参数,即`data`字段的类为`String`,`gc`对象被创建时没有指定类参数,因为编译器可以根据上下文自动推断出类参数为`String`。 2. 接口的使用 在使用接口时,也需要在接口名后面加上尖括号<>,并在括号中指定具体的类参数。例如: ```java GenericInterface<String> gi = new GenericInterface<String>() { private String data; @Override public String getData() { return data; } @Override public void setData(String data) { this.data = data; } }; gi.setData("Hello World"); String data = gi.getData(); ``` 在这个例子中,`GenericInterface`被声明为一个接口,`<String>`指定了具体的类参数,匿名内部类实现了该接口,并使用`String`作为类参数。 3. 方法的使用 在使用方法时,需要在方法名前面加上尖括号<>,并在括号中指定具体的类参数。例如: ```java genericMethod("Hello World"); ``` 在这个例子中,`genericMethod`被声明为一个方法,`<T>`指定了类参数,`T data`表示一个类为`T`的参数,调用时可以传入任何类的参数。 三、的通配符 有时候,我们不知道的具体类,可以使用通配符`?`。通配符可以作为类参数出现在方法的参数类或返回类中,但不能用于声明类或接口。例如: ```java public void printList(List<?> list) { for (Object obj : list) { System.out.print(obj + " "); } } ``` 在这个例子中,`printList`方法的参数类为`List<?>`,表示可以接受任何类的`List`,无论是`List<String>`还是`List<Integer>`都可以。在方法内部,使用`Object`类来遍历`List`中的元素。 四、的继承 类和接口可以继承或实现其他类或接口,可以使用子类或实现类的类参数来替换父类或接口的类参数。例如: ```java public class SubGenericClass<T> extends GenericClass<T> {} public class SubGenericInterface<T> implements GenericInterface<T> { private T data; @Override public T getData() { return data; } @Override public void setData(T data) { this.data = data; } } ``` 在这个例子中,`SubGenericClass`继承了`GenericClass`,并使用了相同的类参数`T`,`SubGenericInterface`实现了`GenericInterface`,也使用了相同的类参数`T`。 五、的限定 有时候,我们需要对的类参数进行限定,使其只能是某个类或接口的子类或实现类。可以使用`extends`关键字来限定类参数的上限,或使用`super`关键字来限定类参数的下限。例如: ```java public class GenericClass<T extends Number> { private T data; public T getData() { return data; } public void setData(T data) { this.data = data; } } public interface GenericInterface<T extends Comparable<T>> { T getData(); void setData(T data); } ``` 在这个例子中,`GenericClass`的类参数`T`被限定为`Number`的子类,`GenericInterface`的类参数`T`被限定为实现了`Comparable`接口的类。 六、的擦除 在Java中,信息只存在于代码编译阶段,在编译后的字节码中会被擦除。在运行时,无法获取的具体类。例如: ```java public void genericMethod(List<String> list) { System.out.println(list.getClass()); } ``` 在这个例子中,`list`的类为`List<String>`,但是在运行时,`getClass`返回的类为`java.util.ArrayList`,因为信息已经被擦除了。 七、的类推断 在Java 7中,引入了钻石操作符<>,可以使用它来省略类参数的声明。例如: ```java List<String> list = new ArrayList<>(); ``` 在这个例子中,`ArrayList`的类参数可以被编译器自动推断为`String`。 八、总结 Java是一个强大的特性,可以提高代码的可读性和安全性,降低代码的耦合度。在使用时,需要注意它的基本语法、使用方法、通配符、继承、限定、擦除和类推断等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值