java基础之泛型,JDK5以后出现的新特性

本文介绍了Java泛型的基本概念及其在集合中的应用,包括如何使用泛型提高程序安全性、优化设计并避免强制类型转换等问题。同时,文章还探讨了泛型在不同场景下的使用方法,如在类、方法和接口中的应用,以及通配符的使用。
摘要由CSDN通过智能技术生成

泛型:

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

        原因:数组直接定义了存储的类型,防止出现其他的类型的元素,集合也像数组一样,直接规定集合的数据类型,针对这种情况,诞生除了泛型这个概念  ===> 泛型的引出可以提供程序的安全性;

        泛型的好处:
                1> 将运行时期异常提前到了编译时期;
  2> 优化了设计,解决了黄色警告线问题;
                3> 避免了强制类型转换;

        举例:

import java.util.ArrayList;
import java.util.Iterator;

public class GenericDemo {

	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)) ;	 //已经定了当前集合时String类型
		
		//遍历
		//获取迭代器
		Iterator<String> it = array.iterator() ;
		while(it.hasNext()) {
			//java.lang.ClassCastException:类转换异常
			String s = it.next() ;   //这里不需要强制类型转换,因为已经定义了集合的类型树String类型
			System.out.println(s);
		}
	}
}

        ArrayList集合存储自定义类型的对象,并遍历:

        举例:

package org.westos_01;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

/**
 * 使用ArrayList集合存储自定义对象并遍历,加入泛型
 * @author Administrator
 *
 */
class Student {

        private String name ;
        private int age ;

        public Student() {
                super();
        }
        public Student(String name, int age) {
                super();
                this.name = name;
                this.age = age;
        }
        public String getName() {
                return name;
        }
        public void setName(String name) {
                this.name = name;
        }
        public int getAge() {
                return age;
        }
        public void setAge(int age) {
                this.age = age;
        }
}

public class GenericDemo2 {

	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());
		}
	}
}
        Object中的泛型:

                在早期的时候,使用Object类型代表任意类型,向上转型没有问题,使用向下转型的时候,可能会出现问题(需要的类型有问题),这个时候就需要引入泛型操作;

                举例:

class ObjectTool<T> {    //T表示可以接受的数据类型为任意类型

        private T obj ;

        public T getObj() {
                return obj ;
        }

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

public class ObjectToolDemo {
	
	public static void main(String[] args) {
		
		//创建ObjectTool对象
		ObjectTool<String> ot = new ObjectTool<String>() ;
		
		//赋值
		ot.setObj(new String("高圆圆"));
		String s = ot.getObj() ;
		System.out.println("姓名是:"+s);
		
		//ot.setObj(new Integer(27)); 直接隐藏的问题解决了
		System.out.println("---------------");
		
		ObjectTool<Integer> ot2 = new ObjectTool<Integer>() ;
		ot2.setObj(new Integer(27));
		//ot2.setObj(new String("高圆圆"));
		Integer i = ot2.getObj() ;
		System.out.println("年龄是:"+i);
	}
}
        方法中也可以定义泛型:
public class ObjectTool{

        //泛型是可以在方法上定义的
        public <T> void show(T t) {   //泛型的参数为任意类型
                System.out.println(t);
        }
}
        泛型在接口中:
                两种情况:
//将泛型定义在接口上
public interface Inter<T> {

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

//接口中泛型,子实现类的第一种情况,就是已经知道是什么类型了
public class InterImpl implements Inter<String> {

        @Override
        public void show() {
                System.out.println("hello");
        }
}

//第二种情况,就是不知道具体的类型是什么
public class Inter2Impl<T> implements Inter<T>{

        @Override
        public void show() {
                System.out.println("hello");
        }
}

//测试类
public class InterDemo {

	public static void main(String[] args) {
		
		//第一种情况的测试
		//创建接口的子实现类对象
		Inter<String> i = new InterImpl() ;  //第一种因为定义了String类型,所以只能用String的类型实现
		i.show();
		
		System.out.println("---------------------");
		
		//第二种情况的测试
		Inter<Integer> i2 = new Inter2Impl<Integer>();   //第二种可以使用任何累心进行定义
			i2.show() ;	
		Inter<String> i3 = new Inter2Impl<String>() ;
		i3.show();
				
	}
}
        泛型高级(通配符):
                <?>:代表任意类型Object类型,或者任意的Java类;
                <? extends E>:向下限定,E的子类或者E这个类型;

                <? super E>:向上限定,E及其他的父类;

        举例:

import java.util.ArrayList;
import java.util.Collection;

class Animal{
	
}

class Cat extends Animal {
	
}

class Dog extends Animal{
	
}

public class GenericDemo {
	
	public static void main(String[] args) {
		
                //创建集合对象,泛型如果明确的情况下,前后必须保持一致
                //Collection<Object> c2 = new ArrayList<Cat>() ;   会报错
                //Collection<Object> c3 = new ArrayList<Animal>() ;    会报错
                Collection<Object> c1 = new ArrayList<Object>() ;
		
		
		//<?>:代表任意类型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 Aninal> c11 = new ArrayList<Object>() ;  会报错
		Collection<? extends Object> c8 = new ArrayList<Object>() ;
		Collection<? extends Object> c9 = new ArrayList<Animal>() ;
		Collection<? extends Object> c10 = new ArrayList<Cat>() ;
		
		
		//<? super E>:向上限定,E及其他的父类
		//Collection<? super Animal> c12 = new ArrayList<Cat>() ;   会报错
		Collection<? super Animal> c13 = new ArrayList<Animal>() ;
		Collection<? super Animal> c14 = new ArrayList<Object>() ;
		
	}
}

JDK5以后的新特性:

        增强for循环:
                 格式:
                        for(数据大类型  变量名 : 数组或者集合对象名){
        输出变量即可;
        }
                作用:
                        增强for的出现是替代迭代器的,所以在遍历集合或者遍历数组就可以使用增强for去完成;
                 增强for循环的弊端:
                        如果集合的对象是null,如果再次对集合操作,就会出现异常;

                        解决:对集合进行判断,非空判断解决;

                举例:

public class ForDemo {
	
		public static void main(String[] args) {
			
			//定义一个数组,静态初始化
			int[] arr = {11,22,33,44,55} ;
			//正常的方式,普通for循环
			for(int x = 0 ; x < arr.length ; x ++) {
				System.out.println(arr[x]);
			}
			
			System.out.println("---------------------");
			
			//增强for循环
			for(int a :arr) {
				System.out.println(a);
			}
			
			//定义一个字符串类型的数组
			String[] str = {"hello","world","java","javaee"} ;
			
			//增强for
			for(String s : str) {
				System.out.println(s);
			}
			
			System.out.println("-------------------------");
			
			//创建一个集合
			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 = null ;
			//NullPointerException:如果集合为空遍历的话会报异常
			//解决方法:给集合进行非空判断
			if(list !=null) {
				for(String s:list) {
					System.out.println(s);
				}
			}
			
		}
}
        静态导入:
                 特点:
1> 前提是该方法必须是静态的;
2> 导入到的一个方法的级别;
                 静态导入的格式:
        import  static  包名 . 类名 . 方法名;   ==>  方法必须是静态方法;

                        之前学习的导包:java.util.Scanner;   导入到类的级别;

                举例:

import static java.lang.Math.abs;		//导入到方法的级别
import static java.lang.Math.pow;
public class ImportStaticDemo {
	
	public static void main(String[] args) {
		System.out.println(Math.abs(-100));
		System.out.println(Math.pow(2,3));
		//可以使用带前缀的方式
		System.out.println(java.lang.Math.abs(-100));
		
		System.out.println("-------------------------");
		
		//在测试,直接写方法名,前提静态导入
		//System.out.println(abs(-100));
		
		System.out.println(java.lang.Math.abs(-100));
		System.out.println(pow(2,3));
		
		//本身当前的某个类中的方法名和需要被静态导入的方法名一样,必须加上前缀
		
	}
	
	//Date ---->有两个包下  java.util.Date		java.sql.Date

}
        可变参数:
                当一个方法的参数个数不确定的时候,要使用可变参数;
                 格式:
         修饰符  返回值类型  方法名(数据类型 . . . 变量名){...}
                注意:
         1> 变量名:看成一个数组;

        2> 使用的时候数据类型;

                举例:

public class ArgsDemo {

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

        ArrayList集合存储自定义对象并遍历:

        举例:

package org.westos_01;

import java.util.ArrayList;
import java.util.Iterator;

/**
 *
 * ArrayList集合存储自定义对象并遍历,有几种方式?
 * 		Iterator iterator() ;
 * 		listIterator listiterator();(可以不写)
 * 		普通for循环:size()/get(int index)
 * 		增强for循环	
 */
public class ArrayListTest {
	
	public static void main(String[] args) {
		
		//创建ArrayList集合
		ArrayList<Student> array = new ArrayList<Student>() ;
		
		//创建学生对象
		Student s1 = new Student("张三", 20) ;
		Student s2 = new Student("李四", 19) ;
		Student s3 = new Student("王五", 22) ;
		Student s4 = new Student("赵六", 26) ;
		
		//添加元素
		array.add(s1) ;
		array.add(s2) ;
		array.add(s3) ;
		array.add(s4) ;
		
		//方式1:迭代器遍历:Iterator 
		Iterator<Student> it = array.iterator() ;
		while(it.hasNext()) {
			Student s = it.next() ;
			System.out.println(s.getName()+"----"+s.getAge());
		}
		
		System.out.println("-------------------");
		
		//方式2:普通for
		for(int x = 0 ; x < array.size() ; x ++) {
			Student s = array.get(x) ;
			System.out.println(s.getName()+"----"+s.getAge());
		}
		
		System.out.println("-------------------");
		
		//方式3:增强for循环
		for(Student s : array) {
			System.out.println(s.getName()+"----"+s.getAge());
		}
	}
}

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

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

                举例:

public class ArraysDemo {
	
	public static void main(String[] args) {
		
		//定义数组:
		/*String[] str = {"hello","world","java"} ;
		
		//将数组转换成固定大小的集合
		List<String> list = Arrays.asList(str) ;*/
		
		//一步完成
		List<String> list = Arrays.asList("hello","world","java") ;
		
		//添加元素
		//list.add("javaee") ;// java.lang.UnsupportedOperationException :集合固定的,长度是固定的
		
		//list.remove("world") ;
		list.set(1, "javaee"); //将指定位置的元素修改为"javaee"
		//增强for
		for(String s:list) {
			System.out.println(s);
		}
	}
}
        综合练习1:
package org.westos_03;

import java.util.ArrayList;
import java.util.Random;

/**
 * 
 * 需求:求10个1~20之间的随机数,要求数据不能重复    	set集合
 * 
 *分析:
 *	可以使用数组,数组的长度固定,不够好,使用集合去做
 *
 * 创建一个随机数类对象
 * 	Random
 * 
 * 	    获取指定的随机数的范围:
 * 		int nextInt()	 ;  获取的int类型的范围
 * 		int nextInt(int n)	;获取1~n之间的数据 ,[0,n)
 * 			
 * 创建一个ArrayList集合对象,元素类型:Integer类型
 * 定义统计遍历:count		是从0开始
 * 判断如果统计遍历小于10
 * 			先计算出1-20之间的随机数,还需要判断集合中是否包含这些元素
 * 			如果不包含,添加,count++
 * 			包含,重复,不搭理了....
 * 
 * 大于10,不搭理
 * 
 * 遍历即可
 */
public class ArrayListTest {
	
	public static void main(String[] args) {
		//创建随机数类对象
		Random r = new Random() ;
		
		//创建一个ArrayList集合
		ArrayList<Integer> array = new ArrayList<Integer>() ;
		
		//定义统计变量
		int count = 0 ;
		
		//判断统计变量的个数
		while(count <10) {
			//个数符合的情况下,计算出1-20之间的随机数
			int number = r.nextInt(20) +1 ;
			
			//需要判断集合总是发包含这个number
			if(!array.contains(number)) {
				array.add(number) ;
				count ++ ;
			}
		}
		
		//增强for
		for(Integer i : array) {
			System.out.println(i);
		}
	}
}
        综合练习2:
package org.westos_02;

import java.util.ArrayList;
import java.util.HashSet;

/**
 *需求
	集合的嵌套遍历

	有一个Java基础班,里面有很多学生,把一个班级集合:ArrayList<Student>
	
不止一个Java基础班,这个时候就定义大集合:ArrayList<ArrayList<Student>>

有三个基础班,分别遍历每一个班里面学生信息:(name,age) 
 *
 */
class Student {

	private String name ;
	private int age ;
	
	public Student() {
		super();
	}

	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}	
}

public class ArrayListTest {
	
	public static void main(String[] args) {
		
		//创建一个大的集合
		ArrayList<ArrayList<Student>> bigArrayList = new ArrayList<ArrayList<Student>>() ;
		
		//创建第一个班的集合对象
		ArrayList<Student> firstArray = new ArrayList<Student>() ;
		//创建学生对象
		Student s1 = new Student("曹操",35) ;//后知后觉
		Student s2 = new Student("诸葛亮", 29);//先知先觉
		Student s3 = new Student("蒋干", 30) ;//不知不觉
		
		//给第一个班添加元素
		firstArray.add(s1) ;
		firstArray.add(s2) ;
		firstArray.add(s3) ;
		
		//将第一个集合添加到大集合中
		bigArrayList.add(firstArray) ;
		
		//创建第二个班集合对象
		ArrayList<Student> secondArray = new ArrayList<Student>() ;
		Student s11 = new Student("宋江",38) ;
		Student s22 = new Student("鲁智深", 29);
		Student s33 = new Student("武松", 30) ;
		
		secondArray.add(s11) ;
		secondArray.add(s22) ;
		secondArray.add(s33) ;
		
		//添加到大集合
		bigArrayList.add(secondArray) ;
		
		//创建第三个集合对象
		ArrayList<Student> thirdArray = new ArrayList<Student>() ;
		Student s111 = new Student("高圆圆",38) ;
		Student s222 = new Student("唐嫣", 29);
		Student s333 = new Student("刘若英", 30) ;
		
		thirdArray.add(s111) ;
		thirdArray.add(s222) ;
		thirdArray.add(s333) ;
		//添加到集合
		bigArrayList.add(thirdArray) ;
		
		//增强for遍历:大集合
		for(ArrayList<Student> array: bigArrayList) {
			for(Student s:array) {
				System.out.println(s.getName()+"---"+s.getAge());
			}
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值