JDK5的新特性

JDK5的新特性

1.泛型

泛型的好处
a. 提高了程序的安全性
b. 将运行期遇到的问题转移到了编译期
c. 省去了类型强转的麻烦

设计原则:及早失败原则。
a. 方便查找原因
b. 节省计算机资源

①泛型类

定义:把泛型定义在类上面,一个类可以定义多个泛型
泛型命名规则:
只要满足标识符的规则就行,规范:一般用大写字母表示:
T:type
E:element
K:key
V:value
注意事项:泛型只能代指引用数据类型。所以集合只能存储类。

public class Tool<T> {  //T类比形参
T obj;
public T getObj() {
	return obj;
}
public void setObj(T obj) {
	this.obj = obj;
}
}

public class GenericDemo1 {
public static void main(String[] args) {
	Tool<String> tool = new Tool<String>();   //new Tool<String>中的String可类比实参,告诉引用变量参数类型。
	Tool<String> tool = new Tool<>();  //  JDK1.7提供了菱形操作符,可以利用类型推断机制推断出对象的类型。
}
}

②泛型方法

意义:如果不使用泛型方法,当我们需要一个方法支持多种类型时,要定义多种方法来支持多种数据类型,或者把参数类型定义为Object。但是需要强制类型转换,不然不能用那些类的特有方法。
定义:把泛型定义在方法上
范围:在方法的声明和方法体内
格式:public <泛型类型> 返回类型 方法名(…)

Q:为什么泛型定义要在返回值类型前面?
A:因为返回值类型也可以是泛型,所以要先定义

Q:有泛型方法的类一定是泛型类吗?
A:不是!

public class Tool {
	public <T> T echo(T t) {  
		return t;
	}
}
class GenericDemo2 {
	public static void main(String[] args) {
			Tool tool = new Tool();
			String s = "Hello";
			String s = tool.echo(s);  //s把参数类型传递给了T。一定有参数s,因为这样泛型才有意义。
	}
}
③泛型接口

把泛型定义在接口上;
范围:整个接口内

public interface Auto<T> {
	T run(T t);
}

泛型接口实现的类:
a.普通类
public class Car implements Auto<String> {
	@Override
	public String run(String s) {
		return null;
	}
}
public static void main(String[] args) {
	Car car = new Car();
	String s = car.run("hello");
}
b.泛型类
public class Bus<T> implements Auto<T> {
	@Override
	public T run(T s) {
		return null;
	}
}
public static void main(String[] args) {   //类型传递过程:创建对象 -->  Bus<T> --> Auto<T>
	Bus<String> bus = new Bus<>();
	String s = bus.run("hello");
}
④泛型通配符(了解):

作用:为了能有像数组那样的性质,但又不想有数组那样的弊端。

String[] strs = {"hello", "world", "java"};
Object[] objs = strs;  // String[]虽然不是Object[]的子类,但Object[]仍然可以指向String[]。(那样的性质 Object[]可以指向String[])
objs[0] = new Object();  // 会出现ArrayStoreException。(那样的弊端)
/*
List<String> strs = new ArrayList<>();
strs.add("hello");
strs.add("world");
strs.add("java");
List<Object> objs = strs;   // 不允许
*/
  1. 泛型通配符<?>:可以匹配任意类型
  2. ? extends E:可以匹配E及其子类
  3. ? super E:可以匹配E及其父类
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

Collection<Object> c1 = new ArrayList<Object>();  //没有通配符的情况 
Collection<Object> c2 = new ArrayList<Animal>();  //不允许
Collection<Object> c3 = new ArrayList<Cat>();  //不允许
Collection<Object> c4 = new ArrayList<Dog>();  //不允许

Collection<?> c1 = new ArrayList<Object>();  //<?>  可以匹配任意类
Collection<?> c2 = new ArrayList<Animal>();  //允许
Collection<?> c3 = new ArrayList<Cat>();  //允许
Collection<?> c4 = new ArrayList<Dog>();  //允许
c3.add(new Cat());    //编译看左边,为了避免数组的问题,不允许添加元素
c3.add(new Dog());  
c3.add(new Object());

Collection<? extends Animal> c1 = new ArrayList<Object>();  //不允许
Collection<? extends Animal> c2 = new ArrayList<Animal>();  //可以匹配Animal及其子类
Collection<? extends Animal> c3 = new ArrayList<Cat>();
Collection<? extends Animal> c4 = new ArrayList<Dog>();
c3.add(new Cat());  //编译看左边,为了避免数组的问题,不允许添加元素
c3.add(new Dog());
c3.add(new Animal());

Collection<? super Animal> c1 = new ArrayList<Object>();  //可以匹配Animal及其父类
Collection<? super Animal> c2 = new ArrayList<Animal>();
Collection<? super Animal> c3 = new ArrayList<Cat>();  //不允许
Collection<? super Animal> c4 = new ArrayList<Dog>();  //不允许
c2.add(new Animal());  //允许
c2.add(new Object());  //不允许
⑤泛型擦除

将字节码文件.class反编译之后,我们不会看到泛型,说明在编译时会“擦除”泛型信息。
E ----> Object
? extends E —> E
? super E —> Object

练习:
向一个List<String>中添加一个整数。
因为编译后的.class字节码文件没有泛型信息,所以可以通过反射绕过泛型检查。

List<String> list = new ArrayList<>();
list.add("hello");
list.add("world");
list.add("java");
int i = 10;
Class<? extends List> c1 = list.getClass();
Method addMethod = c1.getMethod("add", Object.class)  E ---> Object   add(E e)
addMethod.invoke(list,i);
System.out.println(list); //[hello, world, java, 10]

//获取该值
//方法一:反射

//方法二:强转(子类转父类)
Object obj = list.get(3);
Integer a = (Integer) obj;
System.out.println(a);  // 10
⑥Collection类的toArray方法
<T> T[] toArray(T[] a)
如果数组a能够容纳下集合的元素,那么就会把元素放入数组a中
如果数组a不能够容纳下集合的元素,那么就会创建一个新数组,并把元素放入新数组中。

Collection<String> c = new ArrayList<>();
c.add("hello");
c.add("world");
c.add("java");

String[] arr = new String[3];
String strs = c.toArray(str);
System.out.println(Arrays.toString(strs));  //[hello, world, java]
System.out.println(Arrays.toString(arr));  //[hello, world, java]
System.out.println(arr == strs);   // true

String[] arr = new String[2];
String strs = c.toArray(str);
System.out.println(Arrays.toString(strs));   //[null, null]
System.out.println(Arrays.toString(arr)); //[hello, world, java]
System.out.println(arr == strs);   // false

正确使用方式:
String[] strs = new String[c.size()];
c.toArray(strs);  
System.out.println(Arrays.toString(strs));
⑦数组转化为集合(视图方法)
Arrays:
static <T> List<T> asList(T... a)   //视图方法

String[] strs = {"hello", "world", "java"};
List<String> list = Arrays.asList(strs);
System.out.println(list);

list.set(0, "Hello");  //修改集合元素
System.out.println(list);  //[Hello, world, java]
System.out.println(Arrays.toString(strs)); //[Hello, world, java]

list.add("wuhan");  //增加集合元素  UnsupportedOperationException。底层是一个数组,大小不能改变
System.out.println(list);  
System.out.println(Arrays.toString(strs)); 

list.remove(0);  //删除集合元素  UnsupportedOperationException。底层是一个数组,大小不能改变
System.out.println(list);  
System.out.println(Arrays.toString(strs)); 

2.foreach方法

①格式:

for(元素数据类型 变量 : 数组或Collection集合) {
使用变量即可,该变量即元素
}

②好处:
  1. 简化数组和集合的遍历操作;
  2. 增强代码可读性
③坏处:
  1. 不能修改集合或者数组,只能查看元素
  2. 无法遍历部分元素
  3. 没有索引信息,不能操作索引
④底层实现:

遍历对数组还是进行了特殊处理
集合还是运用了迭代器

Q:那些对象可以使用foreach循环
A:数组和实现了Iterable接口的对象。

String[] s = {"hello", "world", "java"};
for(String element : s) {
	System.out.println(element);
}

List<String> list = new ArrayList<>();
list.add("hello");
list.add("world");
list.add("java");
for(String s : list) {
	System.out.println(s);
}

3.可变长参数

JDK1.5之前是使用数组。

①格式:

方法名(数据类型… 变量名)

②原理:

编译完成后实际底层是一个数组

③注意事项:

可变长参数必须在参数列表后面
Q:一个方法最多可以有几个可变长参数
A:一个
Q:如果一个方法需要多个"可变长参数",该怎么办?
A:前面的可以使用数组

int sum = add(1, 2, 3, 4);

public static int add(int... arr) {
	int sum = 0;
    for(int i : arr) sum += i;
    return sum;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值