Java泛型以及jdk5以后的新特性

 

1.泛型的引入

 

 

[需求]ArrayList集合存储元素并遍历

public static void main(String[] args) {
		
		
		//创建集合对象
		ArrayList<String> array = new ArrayList<String>() ;
		
		//添加元素
		array.add("hello") ;
		array.add("world") ;
		array.add("java") ;
		array.add(new Integer(100)) ;	
		
		//遍历
		//获取迭代器
		Iterator<String> it = array.iterator() ;
		while(it.hasNext()) {
			//java.lang.ClassCastException:类转换异常
			String s = (String)it.next() ;
			System.out.println(s);
		}
	}

 

问题:使用ArrayList集合存储元素遍历的时候,按照正常的操作出现了问题,
    当前ArrayList集合中存储了两种类型的元素分别String和Integer类型,在遍历的时候,使用的是String接收的,对于Integer类型就出现了异常!
回想数组:
   String[] str = new String[3] ;
   str[0] = "hello" ;
   str[1] = "world" ;
   str[2] = 100 ;  错误的,
 
 数组直接定义了存储的类型,防止出现其他类型的元素,集合能不能也像数组一样,直接规定我们集合的存储类型?

 针对这种情况,Java提供了一种技术:泛型

 

2.泛型的概念

泛型:将明确的集合类型的工作推迟到了创建对象或者调用方法的时候,属于一种参数化类型,可以作为参数传递.

      <数据类型>   --- 引用数据类型

 

 

泛型的好处:
    1)将运行时期异常提前到了编译时期
    2)优化了设计,解决了黄色警告线问题
    3)避免了强制类型转换
    4)提高了程序的安全性!

 

[需求]使用ArrayList集合存储自定义对象并遍历,加入泛型

public static void main(String[] args) {
		
		//创建集合对象
		ArrayList<Student> array = new ArrayList<Student>() ;  //=号右边的泛型:泛型推断
		
		//创建学生对象
		Student s1 = new Student("王昭君",25) ; 
		Student s2 = new Student("西施",27) ; 
		Student s3 = new Student("杨贵妃",25) ; 
		Student s4 = new Student("貂蝉",28) ; 
		
		//添加到集合中
		array.add(s1) ;
		array.add(s2) ;
		array.add(s3) ;
		array.add(s4) ;
		
		//获取迭代器
		Iterator<Student> it = array.iterator() ;
		while(it.hasNext()) {
			Student s = it.next() ;
			System.out.println(s.getName()+"----"+s.getAge());
		}
		
		System.out.println("------------------");
		
		//普通for循环
		for(int x = 0 ; x < array.size() ; x ++) {
			Student s = array.get(x) ;
			System.out.println(s.getName()+"---"+s.getAge());
		}
	}

3.泛型的应用

 

 

1)将泛型定义在类上:解决了向下类型转换出现的问题:ClassCastException

 

public class ObjectTool<T> {

	private T obj ;
	
	public T getObj() {
		return obj ;
	}
	
	public void setObj(T obj) {
		this.obj = obj ;
	}
}

               //创建ObjectTool对象
		ObjectTool<String> ot = new ObjectTool<String>() ;
		
		//赋值
		ot.setObj(new String("高圆圆"));
		String s = ot.getObj() ;
		System.out.println("姓名是:"+s);

 

2)将泛型定义在方法上

 

public class ObjectTool{
	
	//泛型是可以在方法上定义的
	public <T> void show(T t) {
		System.out.println(t);
	}
}

               //创建ObjectTool类的对象
		ObjectTool ot = new ObjectTool() ;
		ot.show("hello");
		ot.show(true);
		ot.show(100);

 

3)将泛型定义在接口上

//将泛型定义在接口上
public interface Inter<T> {

	//接口中变量是常量: public static final  int num ;
	
	public abstract void show() ; //抽象方法
	
	
}

public static void main(String[] args) {
		
		//第一种情况的测试
		//创建接口的子实现类对象
		Inter<String> i = new InterImpl() ;
		i.show();
		
		System.out.println("---------------------");
		
		//第二种情况
		Inter<Integer> i2 = new InterImpl<Integer>();
			i2.show() ;
			
		Inter<String> i3 = new InterImpl<String>() ;
		i3.show();
				
	}

 

4.泛型高级(通配符)

           -------能看懂就行

 

 <?>  :代表任意类型Object类型,或者任意的Java类
 <? extends E>:向下限定,E的子类或者E这个类型
 <? super E>:向上限定,E及其他的父类

class Animal{
	
}
class Cat extends Animal {
	
}

class Dog extends Animal{
	
}

public static void main(String[] args) {
		
		//创建集合对象,泛型如果明确的情况下,前后必须保持一致
		Collection<Object> c1 = new ArrayList<Object>() ;
//		Collection<Object> c2 = new ArrayList<Cat>() ;//错误
//		Collection<Object> c3 = new ArrayList<Animal>() ;//错误
		
		
		//<?>  :代表任意类型Object类型,或者任意的Java类 
		Collection<?> c4 = new ArrayList<Object>() ;
		Collection<?> c5 = new ArrayList<Animal>() ;
		Collection<?> c6 = new ArrayList<Dog>() ;
		Collection<?> c7= new ArrayList<Cat>() ;
		
//		<? extends E>:向下限定,E的子类或者E这个类型
		Collection<? extends Object> c8 = new ArrayList<Object>() ;
		Collection<? extends Object> c9 = new ArrayList<Animal>() ;
		Collection<? extends Object> c10 = new ArrayList<Cat>() ;
//		Collection<? extends Aninal> c11 = new ArrayList<Object>() ;//错误
		
//		<? super E>:向上限定,E及其他的父类
//		Collection<? super Animal> c12 = new ArrayList<Cat>() ;//错误
		Collection<? super Animal> c13 = new ArrayList<Animal>() ;
		Collection<? super Animal> c14 = new ArrayList<Object>() ;
		
	}

5.Jdk5以后的新特性

 

 

增强for,静态导入,可变参数,泛型,自动拆装箱...

(1)增强for

    1)增强for循环的格式
       for(数据大类型  变量名 : 数组或者集合对象名){
        输出变量即可!
       }

//定义一个字符串类型的数组
			String[] str = {"hello","world","java","javaee"} ;
			//直接增强for
			for(String s : str) {
				System.out.println(s);
			}

 

//创建一个集合
			List<String> list = new ArrayList<String>() ;
			list.add("hello") ;
			list.add("world") ;
			list.add("java") ;
			//直接增强for
			for(String s:list) {
				System.out.println(s);
			}

 

[注意]

  对上述集合,遍历list集合,判断如果有"world"元素,给集合添加一个元素(javaee)

//遍历list集合,判断如果有"world"元素,给集合添加一个元素(javaee)
			for(String s: list) {  //使用size()和get(int index)相结合...
				//java.util.ConcurrentModificationException :并发修改异常 
				//增强for的出现就是用来替代迭代器的!
				if("world".equals(s)) {
					list.add("javaee");
				}
			}

 

发现:出现了java.util.ConcurrentModificationException :并发修改异常

增强for的出现时替代迭代器的,所以在遍历集合或者遍历数组就可以使用增强for去完成

 

 

解决方法:使用普通for循环遍历,使用size()和get(int index)相结合...

2)增强for循环的弊端

如果集合的对象是null,如果再次对集合操作,就会出现NullPointerException异常
解决方法:对集合进行判断,非空判断解决

 

                        if(list !=null) {
				for(String s:list) {
					System.out.println(s);
				}
			}

 

(2)静态导入

   1)特点:
       1)前提是该方法必须是静态的
       2)导入到的一个方法的级别

  2)静态导入的格式:
    import static 包名.类名.方法名;

import static java.lang.Math.abs;		//导入到方法的级别
import static java.lang.Math.pow;

	
	public static void main(String[] args) {
		//在测试,直接写方法名,前提静态导入
		System.out.println(abs(-100));
		System.out.println(pow(2,3));
	}	

 

[注意]如果本身当前的某个类中的方法名和需要被静态导入的方法名一样,必须加上前缀

import static java.lang.Math.abs;		//导入到方法的级别
import static java.lang.Math.pow;
public class ImportStaticDemo {
	
	public static void main(String[] args) {
		
		System.out.println(java.lang.Math.abs(-100));
		
		//本身当前的某个类中的方法名和需要被静态导入的方法名一样,必须加上前缀
		
	}
	
	public static void abs() {
		
	}
}

 

(3)可变参数

    1)可变参数:当一个方法的参数个数不确定的时候,要使用可变参数

    2) 格式:
        修饰符 返回值类型  方法名(数据类型...变量名){...}

    3)注意:
 *   1)变量名:看成一个数组
 *   2)使用的时候数据类型后面是3个点...

 [需求]求数据之和 

public class ArgsDemo {

	public static void main(String[] args) {

		//当我们的参数不确定的情况下,就可以使用jdk5一个特性:可变参数
		System.out.println(sum(10,20,30,40,50));
	}
	
	//定义一个参数不确定的方法,通过可变参数操作
	public static int sum(int...a) {
		//求和:将a是多个参数的,看成数组
		
		//先定义最终结果变量
		int result = 0 ;
		//增强for遍历可变参数a
		for(int n :a) {
			result += n ;
		}
		return result;
	}
}	

 

(4)针对数组操作的工具类:Arrays,提供了一个方法:
  public static <T> List<T> asList(T... a) :将数组转换成固定大小的集合

public static void main(String[] args) {
		
		//定义数组:
		String[] str = {"hello","world","java"} ;
		
		//将数组转换成固定大小的集合
		List<String> list = Arrays.asList(str) ;
                //增强for
		for(String s:list) {
			System.out.println(s);
		}
	}

[注意]如果使用此方法,那么集合的长度不可变!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值