黑马程序员_JAVA笔记15——集合框架(泛型)

本文深入讲解Java泛型的概念、优势及应用场景,包括泛型类、泛型方法、泛型接口等核心内容,并探讨泛型在集合框架中的使用,以及泛型的高级应用如通配符和类型限定。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

-------  android培训java培训、期待与您交流! ----------
1、泛型:JDK1.5后出现的新特性,用于解决安全问题,是一个安全机制。
好处:
        将运行时期出现问题ClassCastException异常,转移到编译时期,方便于程序员解决问题,让运行时期问题减少,提高安全。
        避免了强制类型转换的麻烦

泛型理解:数组在定义的时候明确了存储类型,因此只能存储该类型的数据,若存其他类型数据,编译时期会出错。集合没有明确存储类型,任何类型都能存,编译不出错,但是在取数据的时候要注意类型的强制转换,但是一般情况下我们向集合中存的是同一种类型的数据,比如存放姓名,但是你向里存年龄,编译不出错,因为集合可以存任何数据类型的元素,但是在运行时就会出问题,当取姓名时,把年龄取出来了,这就是安全问题,我们一般情况下都尽量把问题在编译时期解决(编译时的问题,程序员解决;运行时出的问题,通常是用户遇到的,用户一般不能解决这种问题,需要程序员解决)。泛型,给集合声明了存储数据类型,提高了安全性,把问题在编译时期解决,同时因为声明了数据类型,也避免了在取数据时数据类型的转换。

泛型格式:通过<>来定义要操作的引用数据类型

在使用java提供的对象时,什么时候使用泛型?
通常在集合框架中很常见,只要见到<>就要定义泛型

其实<>就是用来接收类型的。
当使用集合时,将集合中药存储的数据类型作为参数传递到<>中即可。

示例:
class GenericDemo
{
        public static void main(String[] args)
        {
                TreeSet <String>  al = new TreeSet <String>(new GenComparator());//泛型,指定集合类数据类型
                al.add("fdfd");
                al.add("fffff");
                al.add(3);//有泛型,编译出错;没有泛型,编译通过
                
                Iterator <String>  it = al.iterator();//表明是String类型的Iterator对象
                while(it.hasNext())
                {
                        String s = it.next();
                        //String s = (String)it.next();没有泛型,需类型转换
                        System.out.println(s.length());
                }
        }
}

class GenComparator  implements Comparator< String>//定义泛型
{
        public int compare( String  o1, String  o2)
        {
                int  num = new Integer( o1.length()).compareTo(new Integer( o2.length()));
                //若想倒序,new Integer( o2.length()).compareTo(new Integer( o1.length()));
                 if(num==0)
                        return o2.compareTo(o1);
                return  num;
        }
}

2、泛型类,什么时候使用,当类中要操作的 引用数据类型不确定的时候。基本数据类型不能使用。
早期定义Object来完成扩展
现在可以定义泛型类
class Worker
{
}
class Student
{
}
//这就是泛型类
class GenicClass<QQ>
{
       private  QQ  q ;
        public setGen(QQ q)
        {
                this.q = q;
        }
        public getGen()
        {
                return q;
        }
}
//早期用Object
class GenicClass
{
       private  Object obj ;
        public setGen( Object obj )
        {
                this.obj = obj;
        }
        public getGen()
        {
                return obj;
        }
}
class GenicDemo
{
        public static void main(String[] args)
        {
                //泛型类时
                 GenicClass<Student> gc = new GenicClass<Student>();
                gc.setGen(new Student());
                 Student s=   gc.getGen(); //不需要类型转换
                Worker  w = gc.getGen();//编译报错,将类型转换问题出现在编译时期

                 //没泛型,用Object时
                GenicClass gc = new GenicClass();
                gc.setGen(new Student());
                Student s = (Student)gc.getGen();//必须类型转换,否则编译报错
                Worker w = (Worker)gc.getGen();//编译不报错,运行报错
                
        }
}

3、泛型方法
泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有操作的类型就已经固定了。
//泛型类
class Demo<T>
{
        public void show(T t)
        {
                System.out.println(t);
        }
        public void print(T t)
        {
                System.out.println(t);
        }
}
class GenDemo
{
        public static void main(String[] args)
        {
                Demo<String> d = new Demo<String>();
                d.show("new String");
                d.print("new String")
        }
}

为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。
//泛型方法,方法上定义的类型只在方法内有效
class Demo
{
        public  <T>  void show(T t)
        {
                System.out.println(t);
        }
        public   <Q>void print(Q q)
        {
                System.out.println(t);
        }
}
class GenDemo
{
        public static void main(String[] args)
        {
                Demo d = new Demo();
                 d.show("new String");
                d.print(new Integer(4));
        }
}

//泛型类中也可以定义泛型方法
class Demo<R>
{
         public void Clss(R r)
        {
                System.out.println(t);
        }
        public  <T> void show(T t)
        {
                System.out.println(t);
        }
        public  <Q>void print(Q q)
        {
                System.out.println(t);
        }
          public static <W> void method(W t)
        {
                System.out.println("method");
        } 
}
class GenDemo
{
        public static void main(String[] args)
        {
                Demo<String> d = new Demo<String>();
                d.Clss("fdfdf");
                 d.show("new String");//泛型类对象,在调用泛型类中定义的泛型方法时,使用的不是创建泛型类对象时声明的数据类型,而是使用的泛型方法自身声明的数据类型
                d.print(new Integer(4));

                 Demo.method();//静态方法
        }
}

注意:静态方法不可以访问类上定义的泛型,如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上。

//泛型定义在接口上,
interface Inter<T>
{
        void show(T t);
}
class InterImp implements Inter<String>//类实现接口,并指明数据类型
{
        public void show(String s)
        {
                System.out.println(s);
        }
}

class InterImppp <T> implements Inter<T>//类实现接口,但不指明数据类型
{
        public void show(T t)
        {
                System.out.println(t);
        }
}
class InterDemo
{
        public static void main(String[] args)
        {
                InterImp<String> ii = new InterImp<String>();
                ii.show("DFDf");
                InterImppp<  String  > iip = new InterImppp<  String  >();
                iip.show("FdFG");
        }
}

4、泛型高级应用
class GenericDemo
{
        public static void main(String[] args)
        {
                ArrayList<String> al = new ArrayList<String>();
                al.add("java_1");
                al.add("java_2");
                al.add("java_3");
                al.add("java_4");

                ArrayList<Integer> all = new ArrayList<Integer>();
                all.add(5);
                all.add(6);
                all.add(2);
                all.add(9");

                printCloo(al);
                printCloo(all);
        }
        //没有泛型时,即1.4以前没有泛型时 ,如下写法,虽然可以但不严谨
        public static void printCloo(ArrayList al)
        {
                Iterator it = al.iterator();
                while(it.hasNext());
                        System.out.println(it.next());
        }
        //有泛型时,可以用<?>代替泛型,表示类型不确定.<?>是占位符
         public static void printCloo(ArrayList<?> al)
        {
                Iterator<?> it = al.iterator();
                while(it.hasNext());
                {
                        System.out.println(it.next());
                        System.out.println(it.next().length());//这里不可以,因为类型不明确,不确定是否有length()方法,泛型不能使用类型的特有方法。但是一些所有共用的方法可以用,例如toString()。
                        System.out.println(it.next().toString())
                }
        }

        //有泛型时,可以用<T>,但静态时T需定义
         public static <T>void printCloo(ArrayList<T> al)
        {
                Iterator<T> it = al.iterator();
                while(it.hasNext());
                {
                        T t = it.next();//这里可以对T进行一些操作,但是<?>不能。
                        System.out.println(it.next());
                }
        }
}


//<?>通配符,也可以理解为占位符
泛型的限定
<? extends E>表示既可以是传E 也可以传E的子类。上限。上边限定了
<? super E>表示可以接收E也可以接收E的父类。下限,下边限定了
示例:上限<? extends E>
class Person
{
        private String name;
        Person(String name)
        {
                this.name = name;
        }
        public String getName()
        {
                return name;
        }
}
class Student extends Person
{
        Student(String name)
        {
                super(name);
        }
}
class GenericDemo
{
        public static void main(String[] args)
        {
                ArrayList<Person> al = new ArrayList<Person>();
                al.add(new Person("java_1"));
                al.add(new Person("java_21"));
                al.add(new Person("java_31"));
                al.add(new Person("java_41"));

                ArrayList<Student> all = new ArrayList<Student>();
                all.add(new Student("ssss01"));
                all.add(new Student("ssss02"));
                all.add(new Student("ssss03"));
                all.add(new Student("ssss04"));
                all.add(new Student("ssss05"));

                printCloo(al);
                printCloo(all);
        }
         public static void printCloo(ArrayList <? extends Person>  al)
        {
                Iterator< ? extends Person> it = al.iterator();
                while(it.hasNext());
                {
                        System.out.println(it.next());
                }
        }
}

示例:下限<? super E>
class Person
{
        private String name;
        Person(String name)
        {
                this.name = name;
        }
        public String getName()
        {
                return name;
        }
}
class Student extends Person
{
        Student(String name)
        {
                super(name);
        }
}
class Worker extends Person
{
        Worker(String name)
        {
                super(name);
        }
}
class GenericDemo
{
        public static void main(String[] args)
        {
                TreeSet<Student> al = new TreeSet<Student>(new Comp());
                al.add(new  Student ("java_1"));
                al.add(new  Student ("java_21"));
                al.add(new  Student ("java_31"));
                al.add(new  Student ("java_41"));

                 TreeSet  <Worker> all = new  TreeSet  <Worker>(new Comp());
                all.add(new  Worker ("ssss01"));
                all.add(new  Worker ("ssss02"));
                all.add(new  Worker ("ssss03"));
                all.add(new  Worker ("ssss04"));
                all.add(new  Worker ("ssss05"));

                printCloo(al);
                printCloo(all);
        }
         public static void printCloo(TreeSet <Person> al)//指定父类比较器
        {
                Iterator< Person> it = al.iterator();
                while(it.hasNext());
                {
                        System.out.println(it.next());
                }
        }
}
class Comp implements Comparator< Person >//指定父类比较器,因此其子类都可以使
                                                                             //用,但是在该方法中只能使用父类的方
                                                                             //法,而不能使用子类特有的方法。
{
        public int compare(Person p1,Person p2)
        {
                int num = p1.getName().compareTo(p2.getName());
                return num;
        }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值