黑马程序员----java基础泛型

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

泛型:jdk1.5之后出现的新特性,用于解决安全问题,是一个安全机制

好处:1 将运行时期的问题转移到编译时期,方便程序员解决问题
      2 避免的强制转换的麻烦
      3 提高了编译时期的安全性。

<>:什么时用?当操作的引用数据类型不确定的时候,就用<>将要操作的引用数据类型传入

<>就是一个用于接收具体引用数据类型的参数范围。


在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型。
class Tool<e1,e2,e3,e4>//<>中可以接收多个类型参数;
Tool<String,Demo,Person,Man> t = new Tool<String,Demo,Person,Man>();


注释:泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。

运行时,会将泛型去掉,生成的class文件中时不带泛型的,这个称之为泛型的擦除。
为什么擦除呢?为了去兼容运行时的类加载器(1.4,1.5同一个类加载器)。

泛型的补偿:在运行时通过获取元素的类型进行转换动作,不用使用者再强制转换了。
-------------------------------
泛型在集合中的应用

--------------------------------
泛型在设计时好处
  当函数的具体实现不知道是使用抽象函数,
  当操作的对象类型不确定时使用泛型。
1 泛型类
  当类中操作的引用数据类型不确定的时候就采用泛型。
  calss Tool<T>
   {
      private T t;
      public void get()
      {
         return t;
       }
      public void set(T t)
      {
         this.t = t;
      }
     }
     
     Tool<Person> tool = new Too<Person>();//指定tool操作的对象为Person
                                           // 提高安全性
     tool.set(new Person());
     Worker w = tool.get();//会报异常   (在使用泛型前异常发生在运行时期
                                          现在异常会出现在编译时期)
     

2  泛型方法
   
    public<T>viod show(T str)
  {
    
      System .out.println(str);
    
  }



   静态方法:不能访问类上定义的泛型。
   只能讲泛型定义在方法上
   
   public static <Y> void method(Y obj)
   {
      System.out.println(obj);
   }

3  泛型接口
   
   interface Inter <T>
   {
       public void show(T t);//不明确show参数的具体类型--> 泛型?为啥不定义在方法上?而是定义在类上?
    }                                                      答:即可定义在方法上,也可定义在类上
                                                               只是作用域不同,定义在类上对整个类可见
                                                               定义在方法上:对该方法可见。


   //接口实现类
   class InterImp implements Inter<String>//当实现类知道该接口的方法操作的数据类型时
{
    pulic void show(String t)
    {
       System.out.println(t)
    }
}

  class InterImp<Q> implements Inter<Q>//当实现类不知道该接口的方法操作的数据类型时:可继续在实现类上定义泛型
{
    pulic void show(Q q)
    {
       System.out.println(q)
    }
}

      InterImp<String> inter = new InterImp<String>();//在具体使用时才传参给泛型
      inter.show("dasda");





   interface Inter//当泛型定义在接口方法上时:
{
    public<T> void show(T t);
}

class InterImp implements Inter
{

    @Override
    public <T> void show(T t) {
        // TODO Auto-generated method stub
        System.out.println(t);
    }
    
}





--------------------------
泛型的限定

  public static void printCollection(/*Collection<String>*/Collection<?> c)//当不确定集合中所装元素类型,
                                                                          //但有不调用元素类型具体方法时:可使用泛型通配符 ?
  {
        //Iterator<String> it = c.iterator();
          Iterator<?> it = c.iterator();
        while(it.hasNext())
         {
            //String str = it.next();
              ? str = it.next();
          }
   }

    
   public static <T> void printCollection(Collection<T> c)//当方法上定义泛型T:是希望通过T代表的
                                                          //的具体某一类型,对元素进行一些操作。
  {
        Iterator<T> it = c.iterator();
        while(it.hasNext())
         {
            T str = it.next();
             
          }
   }


  限制上限:
   
   ? extends E:接收E或E的子类型

   public static void printCollection(Collection<? extends Person> c)//需求:集合中装入的是一个体系的对象才能打印。
  {
        Iterator<? extends Person> it = c.iterator();
        while(it.hasNext())
         {
           Person p = it.next();
           System.out.println(p.getName());//因为存储的都是person的子类所有都具备person的方法
             
          }
   }

  限制下限:
  ? super E:接收E或 E的父类型。下限
     public static void printCollection(Collection<? super Student> c)//
  {
        Iterator<? super Student> it = c.iterator();
        while(it.hasNext())
         {
           //Person p = it.next();
           //System.out.println(p.getName());
             System.out.println(it.next());
             
          }
   }

--------------------------------
 上限的体现
 通常对结合中的元素进行取出操作时:可以使用下限
   
 Collection中的
 
 addAll(Collection<? extends E> c);:E时创建Collection时传入的

// Collection<E> c = new Collection<E>;
   Collection<Person> c = new Collection<Person>;: 此时E == Person
 
   往集合中存元素时:通常定义上限。
   因为这样取出时:都是按照上限类型来运算了,这样不会出现类型安全隐患。


  下限的体现
   
  TreeSet (Comparator<? super E> comparator);

   class TreeSet<E>
   {
      TreeSet (Comparator<? super E> comparator);
   }
   
   当TreeSet中装的是学生时?要定义学生的比较器。
   当TreeSet中装的是工人时?要定义工人的比较器。 这两个比较器的实现方式是相同的都是按照Person比较器内容实现的
 
    class TreeSet<Student>
   {
      TreeSet (Comparator<Student> comparator);
   }
    
     class TreeSet<Worker>
   {
      TreeSet (Comparator<Worker> comparator);
   }
   
   class TreeSet<Student>
   {
      TreeSet (Comparator<? super Student> comparator);
   }
    
     class TreeSet<Worker>
   {
      TreeSet (Comparator<? super Worker> comparator);
   }

   要进行比较:得把集合中的元素取出来,所以可以用父类来接收子类的对象

  定义比较器时:
  class compByname implements Comparator<Person>
  {

  }

通配符 ?

  • 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、付费专栏及课程。

余额充值