JAVA泛型的基本使用:

/**
* JAVA泛型的使用
* 定义:泛型的本质是参数化类型,就是说所操作的数据类型被指定为一个参数。
*
* 定义泛型方法的规则
* 1.所有泛型方法声明都有一个类型参数声明部分(由尖括号分割),该类型参数声明部分在方法返回类型之前。
* 2.类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
* 3.泛型方法的声明和普通方法一样,需要注意的是类型参数只能代表引用类型,不能是原始类型(像int,char,double,folat等)
* 4.每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
*
* 类型擦除的说明:泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。
*
* 类型通配符上限和类型通配符下限
* <? extends T>表示该通配符所代表的类型是T类型的子类。
* <? super T>表示该通配符所代表的类型是T类型的父类。
*
* 总结:
* 我们发现,在使用泛型类时,虽然传入了不同的泛型实参,但并没有真正意义上生成不同的类型,传入不同泛型实参的泛型类在内存上只有一个,
* 即还是原来的最基本的类型(本实例中为Box),当然,在逻辑上我们可以理解成多个不同的泛型类型。究其原因,在于Java中的泛型这一概念提出的目的,
* 导致其只是作用于代码编译阶段,在编译过程中,对于正确检验泛型结果后,会将泛型的相关信息擦出,也就是说,成功编译过后的class文件中是不包含任何泛型信息的。
* 泛型信息不会进入到运行时阶段。
* 对此总结成一句话:泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。
*
*
* @author dyq
*
*/
public class GenericTest {
public static void main(String[] args) {
/**
* 泛型方法
*/
//泛型方法的声明和普通方法一样,需要注意的是类型参数只能代表引用类型,不能是原始类型(像int,char,double,folat等)
Integer[] intArr = {1,2,3,4,5};
String[] strArr = {"aaa","bb","ccc"};
printArray(intArr);
printArray(strArr); /**
* 泛型类
*/
Person<String> person = new Person<String>("老板");
System.out.println(person.getPosition()); /**
* 类型通配符
*/
Person<Number> name = new Person<Number>(120);
Person<Integer> age = new Person<Integer>(200);
getData(name);
getData(age);
/**
* 类型通配符上限和类型通配符下限
* <? extends T>表示该通配符所代表的类型是T类型的子类。
* <? super T>表示该通配符所代表的类型是T类型的父类。
*/ }
/**
* 泛型的通配符,类型通配符一般是使用?代替具体的类型参数
*
* @param data
*/
public static void getData(Person<? extends Number> data) {
System.out.println(data.getPosition());
}
/**
* 所有泛型方法声明都有一个类型参数声明部分(由尖括号分割),该类型参数声明部分在方法返回类型之前。
* @param inputArray
*/
public static <E> void printArray(E[] inputArray) {
for(E value : inputArray) {
System.out.printf( "%s ",value);
}
System.out.println();
}
/**
* 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
* @param data
* @return
*/
public static <E> E getName(Person<E> E) {
return E.getPosition();
}
/**
* 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
*/
public static <E,T> E getSex(E a,T b) {
if(b!=null) {
return a;
}else {
return null;
}
}
}
/**
* 泛型类的声明
*/
class Person<T>{
private T position;//职位
public Person(T position) {
this.position = position;
}
public T getPosition() {
return this.position;
}
}

泛型相关面试题

1. Java中的泛型是什么 ? 使用泛型的好处是什么?
泛型是一种参数化类型的机制。它可以使得代码适用于各种类型,从而编写更加通用的代码,例如集合框架。

泛型是一种编译时类型确认机制。它提供了编译期的类型安全,确保在泛型类型(通常为泛型集合)上只能使用正确类型的对象,避免了在运行时出现ClassCastException。

2、Java的泛型是如何工作的 ? 什么是类型擦除 ?
泛型的正常工作是依赖编译器在编译源码的时候,先进行类型检查,然后进行类型擦除并且在类型参数出现的地方插入强制转换的相关指令实现的。

编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。例如List<String>在运行时仅用一个List类型来表示。为什么要进行擦除呢?这是为了避免类型膨胀

3. 什么是泛型中的限定通配符和非限定通配符 ?
限定通配符对类型进行了限制。有两种限定通配符,一种是<? extends T>它通过确保类型必须是T的子类来设定类型的上界,另一种是<? super T>它通过确保类型必须是T的父类来设定类型的下界。泛型类型必须用限定内的类型来进行初始化,否则会导致编译错误。另一方面<?>表示了非限定通配符,因为<?>可以用任意类型来替代。

4. List<? extends T>和List <? super T>之间有什么区别 ?
这和上一个面试题有联系,有时面试官会用这个问题来评估你对泛型的理解,而不是直接问你什么是限定通配符和非限定通配符。这两个List的声明都是限定通配符的例子,List<? extends T>可以接受任何继承自T的类型的List,而List<? super T>可以接受任何T的父类构成的List。例如List<? extends Number>可以接受List<Integer>或List<Float>。在本段出现的连接中可以找到更多信息。

5. 如何编写一个泛型方法,让它能接受泛型参数并返回泛型类型?
编写泛型方法并不困难,你需要用泛型类型来替代原始类型,比如使用T, E or K,V等被广泛认可的类型占位符。泛型方法的例子请参阅Java集合类框架。最简单的情况下,一个泛型方法可能会像这样:

public V put(K key, V value) {
return cache.put(key, value);
}

6. Java中如何使用泛型编写带有参数的类?
这是上一道面试题的延伸。面试官可能会要求你用泛型编写一个类型安全的类,而不是编写一个泛型方法。关键仍然是使用泛型类型来代替原始类型,而且要使用JDK中采用的标准占位符。
7. 编写一段泛型程序来实现LRU缓存?
对于喜欢Java编程的人来说这相当于是一次练习。给你个提示,LinkedHashMap可以用来实现固定大小的LRU缓存,当LRU缓存已经满了的时候,它会把最老的键值对移出缓存。LinkedHashMap提供了一个称为removeEldestEntry()的方法,该方法会被put()和putAll()调用来删除最老的键值对。
8. 你可以把List<String>传递给一个接受List<Object>参数的方法吗?(见上面说明)
对任何一个不太熟悉泛型的人来说,这个Java泛型题目看起来令人疑惑,因为乍看起来String是一种Object,所以List<String>应当可以用在需要List<Object>的地方,但是事实并非如此。真这样做的话会导致编译错误。如果你再深一步考虑,你会发现Java这样做是有意义的,因为List<Object>可以存储任何类型的对象包括String, Integer等等,而List<String>却只能用来存储Strings。

9. Array中可以用泛型吗?
这可能是Java泛型面试题中最简单的一个了,当然前提是你要知道Array事实上并不支持泛型,这也是为什么Joshua Bloch在Effective Java一书中建议使用List来代替Array,因为List可以提供编译期的类型安全保证,而Array却不能。
10. 如何阻止Java中的类型未检查的警告?
如果你把泛型和原始类型混合起来使用,例如下列代码,Java 5的javac编译器会产生类型未检查的警告
,例如List<String> rawList = new ArrayList()
注意: Hello.java使用了未检查或称为不安全的操作;
这种警告可以使用@SuppressWarnings("unchecked")注解来屏蔽。

11、Java中List<Object>和原始类型List之间的区别?
原始类型和带参数类型<Object>之间的主要区别是,在编译时编译器不会对原始类型进行类型安全检查,却会对带参数的类型进行检查,通过使用Object作为类型,可以告知编译器该方法可以接受任何类型的对象,比如String或Integer。这道题的考察点在于对泛型中原始类型的正确理解。它们之间的第二点区别是,你可以把任何带参数的泛型类型传递给接受原始类型List的方法,但却不能把List<String>传递给接受List<Object>的方法,因为会产生编译错误。

12、Java中List<?>和List<Object>之间的区别是什么?
这道题跟上一道题看起来很像,实质上却完全不同。List<?> 是一个未知类型的List,而List<Object>其实是任意类型的List。你可以把List<String>, List<Integer>赋值给List<?>,却不能把List<String>赋值给List<Object>。

List<?> listOfAnyType;
List<Object> listOfObject = new ArrayList<Object>();
List<String> listOfString = new ArrayList<String>();
List<Integer> listOfInteger = new ArrayList<Integer>(); listOfAnyType = listOfString; //legal
listOfAnyType = listOfInteger; //legal
listOfObjectType = (List<Object>) listOfString; //compiler error - in-convertible types

13、List<String>和原始类型List之间的区别.
该题类似于“原始类型和带参数类型之间有什么区别”。带参数类型是类型安全的,而且其类型安全是由编译器保证的,但原始类型List却不是类型安全的。你不能把String之外的任何其它类型的Object存入String类型的List中,而你可以把任何类型的对象存入原始List中。使用泛型的带参数类型你不需要进行类型转换,但是对于原始类型,你则需要进行显式的类型转换。

List listOfRawTypes = new ArrayList();
listOfRawTypes.add("abc");
listOfRawTypes.add(123); //编译器允许这样 - 运行时却会出现异常
String item = (String) listOfRawTypes.get(0); //需要显式的类型转换
item = (String) listOfRawTypes.get(1); //抛ClassCastException,因为Integer不能被转换为String List<String> listOfString = new ArrayList();
listOfString.add("abcd");
listOfString.add(1234); //编译错误,比在运行时抛异常要好
item = listOfString.get(0); //不需要显式的类型转换 - 编译器自动转换

JAVA基础部分复习(三、泛型)的更多相关文章

  1. Java基础之多态和泛型浅析

    Java基础之多态和泛型浅析 一.前言: 楼主看了许多资料后,算是对多态和泛型有了一些浅显的理解,这里做一简单总结 二.什么是多态? 多态(Polymorphism)按字面的意思就是“多种状态”.在面 ...

  2. java基础解析系列(三)---HashMap

    java基础解析系列(三)---HashMap java基础解析系列 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)-- ...

  3. Java基础知识点(三)

    前言:准备将Java基础知识点总结成一个系列,用于平常复习并加深理解.每篇尽量做到短小精悍,便于阅读. 1.Math类中相关函数 Math.floor(x):返回不大于x的最大整数.eg:Math.f ...

  4. JAVA基础部分复习(一、8中基础类型,以及String相关内容)

    以下是关于java中8种基本类型的介绍说明: package cn.review.day01; /** * java基础复习,8种数据类型 * (byte,short,long,int,double, ...

  5. JAVA基础学习-集合三-Map、HashMap,TreeMap与常用API

    森林森 一份耕耘,一份收获 博客园 首页 新随笔 联系 管理 订阅 随笔- 397  文章- 0  评论- 78  JAVA基础学习day16--集合三-Map.HashMap,TreeMap与常用A ...

  6. java 基础知识(三)

    Arraylist与Vector的区别 清浅池塘 程序员,专栏:Java那些事儿唯一作者,咨询前请先点详细资料   162 人赞同了该文章 这几天工作有点忙,有很多代码需要写,更新文章有点慢,说声抱歉 ...

  7. Java基础之浅谈泛型

    简单的介绍了Java泛型类型的使用.上手容易,深入很难.

  8. java基础学习总结三(jdk7新特性、变量(局部变量和成员变量)、常量以及运算符)

    一:jdk7新特性 可以表示二进制数值,以0b开头,中间可以使用下划线_分隔符.如下: @Test /** * 测试jdk新特性 */ public void testJdk7(){ int a=0b ...

  9. Java基础加强总结(三)——代理(Proxy)

    一.代理的概念 动态代理技术是整个java技术中最重要的一个技术,它是学习java框架的基础,不会动态代理技术,那么在学习Spring这些框架时是学不明白的. 动态代理技术就是用来产生一个对象的代理对 ...

随机推荐

  1. django学习之——模版

    为了减少模板加载调用过程及模板本身的冗余代码,Django 提供了一种使用方便且功能强大的 API ,用于从磁盘中加载模板, 要使用此模板加载API,首先你必须将模板的保存位置告诉框架. 设置的保存文 ...

  2. Django信息安全相关之CSRF和XSS

    什么是xss攻击 xss攻击:黑客把恶意的JS脚本提交到后端,后端把恶意脚本渲染显示出来     什么是CSRF? 1.你登录建行官网后 你的浏览器就保存了建行网站的cokie,(如果不关闭这个页面c ...

  3. 【转】Vue-详解设置路由导航的两种方法: <router-link :to="..."> 和router.push(...)

    一.<router-link :to="..."> to里的值可以是一个字符串路径,或者一个描述地址的对象.例如: // 字符串 <router-link to= ...

  4. Mysql 在 Windows环境下安装:应用程序无法正常启动0xc000007b

    DirectX 修复工具 v3.7增强版 链接: https://pan.baidu.com/s/135pZUNwpXcMZjyLB41sQCg 密码: gtb5

  5. ci框架memcached使用

    首先第一步需要安装memcached扩展 安装方法这里就不叙述了 application/config/memcached.php配置 $config = array( 'default' => ...

  6. Uva LA 3902 - Network 树形DP 难度: 0

    题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

  7. Unity运行错误代码处理

    1.Unity在运行时出现如图错误,但不影响运行效果展示. 2.错误原因:代码不规范. 3.检查代码,查看变量是否定义正确.

  8. commons-logging,log4j和jdklog的调用方式

    commons-logging包含log4j和jdklog. commons-logging: Log log= LogFactory.getLog(getClass());//commons log ...

  9. python全栈开发笔记---基本数据类型--数字型魔法

    数字  int a1 =123 a2=456 int 讲字符串转换为数字 a = " #字符串 b = int(a) #将字符串转换成整形 b = b + 1000 #只有整形的时候才可以进 ...

  10. jenkins+findbugs+checkstyle+PMD静态代码检查(二)

    可以根据自己的需求选中对应的插件进行配置(不一定非要同时配置三个插件) jenkins:持续集成的工具 fundbugs:检测代码静态错误的插件  例如:定义了没有用到的对象,string类型的比较使 ...