Num1:请不要在新代码中使用原生类型

泛型类和接口统称为泛型。每种泛型定义一组参数化的类型,构成格式是:类或接口名称,接着用<>把对应于泛型形式类型的参数的实际参数列表括起来。比如:List是一个参数化的类型,表示元素类型为String的列表。最后一点,每个泛型都定义一个原生类型,raw type,即不带任何实际类型参数的泛型名称。

示例代码:

public class Raw {
// Uses raw type (List) - fails at runtime! - Page 112
public static void main(String[] args) {
List<String> strings = new ArrayList<String>();
unsafeAdd(strings, new Integer(42));
String s = strings.get(0); // Compiler-generated cast
} private static void unsafeAdd(List list, Object o) {
list.add(o);
} // Use of raw type for unknown element type - don't do this! - Page 113
static int rawNumElementsInCommon(Set s1, Set s2) {
int result = 0;
for (Object o1 : s1)
if (s2.contains(o1))
result++;
return result;
} // Unbounded wildcard type - typesafe and flexible - Page 113
static int numElementsInCommon(Set<?> s1, Set<?> s2) {
int result = 0;
for (Object o1 : s1)
if (s2.contains(o1))
result++;
return result;
}
}

从Java1.5发行版本开始,Java就提供了一种安全的替代方法,称作无限制的通配符类型,如果使用泛型,但不确定或者不关心实际的类型参数,就可以使用一个问号代替。

那么无限制通配类型Set<?>和原生类型Set之间有什么区别呢?通配符类型是安全的,原生类型则不安全。

Num2:消除非受检警告

当使用泛型编程时,会遇到许多编译器警告,那么该如何消除?

可以用@SuppressWarnings("unchecked")这个注解来禁止警告。需要注意的是,每当使用@SuppressWarnings("unchecked")注解时,都要添加一条注释,说明为什么这么做是安全的,这样可以帮助其他人理解代码,更重要的是,可以尽量减少其他人修改代码后导致计算不安全的概率。

Num3:列表优先于数组

数组与泛型相比,有两个重要的不同点。

首先,数组是协变的,泛型则是不可变的。

第二大区别:数组是具体化的,因此数组会在运行时才知道并检查它们的元素类型约束。相比之下,泛型则是通过擦除来实现的,因此泛型只在编译时强化它们的类型信息,并在运行时丢弃它们的元素类型信息。

示例代码:

public class Reduction {
static <E> E reduce(List<E> list, Function<E> f, E initVal) {
List<E> snapshot;
synchronized (list) {
snapshot = new ArrayList<E>(list);
}
E result = initVal;
for (E e : snapshot)
result = f.apply(result, e);
return result;
} // A few sample functions
private static final Function<Integer> SUM = new Function<Integer>() {
public Integer apply(Integer i1, Integer i2) {
return i1 + i2;
}
}; private static final Function<Integer> PRODUCT = new Function<Integer>() {
public Integer apply(Integer i1, Integer i2) {
return i1 * i2;
}
}; private static final Function<Integer> MAX = new Function<Integer>() {
public Integer apply(Integer i1, Integer i2) {
return Math.max(i1, i2);
}
}; private static final Function<Integer> MIN = new Function<Integer>() {
public Integer apply(Integer i1, Integer i2) {
return Math.min(i1, i2);
}
}; public static void main(String[] args) {
List<Integer> intList = Arrays.asList(2, 7, 1, 8, 2, 8, 1, 8, 2, 8); // Reduce intList using each of the above reducers
System.out.println(reduce(intList, SUM, 0));
System.out.println(reduce(intList, PRODUCT, 1));
System.out.println(reduce(intList, MAX, Integer.MIN_VALUE));
System.out.println(reduce(intList, MIN, Integer.MAX_VALUE));
}
}

Num4:优先考虑泛型类和方法

示例类代码:

public class Stack<E> {
private E[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16; // The elements array will contain only E instances from push(E).
// This is sufficient to ensure type safety, but the runtime
// type of the array won't be E[]; it will always be Object[]!
@SuppressWarnings("unchecked")
public Stack() {
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
} public void push(E e) {
ensureCapacity();
elements[size++] = e;
} public E pop() {
if (size == 0)
throw new EmptyStackException();
E result = elements[--size];
elements[size] = null; // Eliminate obsolete reference
return result;
} public boolean isEmpty() {
return size == 0;
} private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
} // Little program to exercise our generic Stack
public static void main(String[] args) {
Stack<String> stack = new Stack<String>();
for (String arg : args)
stack.push(arg);
while (!stack.isEmpty())
System.out.println(stack.pop().toUpperCase());
}
}

如果类可以从泛型中收益一般,方法也一样,静态工具方法尤其适合于泛型化。

示例方法代码:单例工厂模式

public interface UnaryFunction<T> {
T apply(T arg);
} public class GenericSingletonFactory {
// Generic singleton factory pattern
private static UnaryFunction<Object> IDENTITY_FUNCTION = new UnaryFunction<Object>() {
public Object apply(Object arg) {
return arg;
}
}; // IDENTITY_FUNCTION is stateless and its type parameter is
// unbounded so it's safe to share one instance across all types.
@SuppressWarnings("unchecked")
public static <T> UnaryFunction<T> identityFunction() {
return (UnaryFunction<T>) IDENTITY_FUNCTION;
} // Sample program to exercise generic singleton
public static void main(String[] args) {
String[] strings = { "jute", "hemp", "nylon" };
UnaryFunction<String> sameString = identityFunction();
for (String s : strings)
System.out.println(sameString.apply(s)); Number[] numbers = { 1, 2.0, 3L };
UnaryFunction<Number> sameNumber = identityFunction();
for (Number n : numbers)
System.out.println(sameNumber.apply(n));
}
}

示例方法代码:静态方法模式

public class GenericStaticFactory {
// Generic static factory method
public static <K, V> HashMap<K, V> newHashMap() {
return new HashMap<K, V>();
} public static void main(String[] args) {
// Parameterized type instance creation with static factory
Map<String, List<String>> anagrams = newHashMap();
}
}

泛型方法一个显著特征:无需明确指定类型参数的值,不像调用泛型构造器的时候必须指定一个类型。

简而言之,使用泛型比使用需要在客户端代码中进行转换的类型来的更加安全,也更加容易。

【Java基础】泛型的更多相关文章

  1. 一天一个Java基础——泛型

    这学期的新课——设计模式,由我仰慕已久的老师传授,可惜思维过快,第一节就被老师挑中上去敲代码,自此在心里烙下了阴影,都是Java基础欠下的债 这学期的新课——算法设计与分析,虽老师不爱与同学互动式的讲 ...

  2. Java 基础 -- 泛型、集合、IO、反射

    package com.java.map.test; import java.util.ArrayList; import java.util.Collection; import java.util ...

  3. java基础-泛型举例详解

    泛型 泛型是JDK5.0增加的新特性,泛型的本质是参数化类型,即所操作的数据类型被指定为一个参数.这种类型参数可以在类.接口.和方法的创建中,分别被称为泛型类.泛型接口.泛型方法. 一.认识泛型 在没 ...

  4. Java基础 - 泛型详解

    2022-03-24 09:55:06 @GhostFace 泛型 什么是泛型? 来自博客 Java泛型这个特性是从JDK 1.5才开始加入的,因此为了兼容之前的版本,Java泛型的实现采取了&quo ...

  5. java基础-泛型3

    浏览以下内容前,请点击并阅读 声明 8 类型擦除 为实现泛型,java编译器进行如下操作进行类型擦除: 如果类型参数有限制则替换为限制的类型,如果没有则替换为Object类,变成普通的类,接口和方法. ...

  6. java基础 泛型

    泛型的存在,是为了使用不确定的类型. 为什么有泛型? 1. 为了提高安全 2. 提高代码的重用率 (自动 装箱,拆箱功能) 一切好处看代码: package test1; import java.la ...

  7. java基础-泛型2

    浏览以下内容前,请点击并阅读 声明 6 类型推测 java编译器能够检查所有的方法调用和对应的声明来决定类型的实参,即类型推测,类型的推测算法推测满足所有参数的最具体类型,如下例所示: //泛型方法的 ...

  8. java基础-泛型1

    浏览以下内容前,请点击并阅读 声明 泛型的使用能使类型名称作为类或者接口定义中的参数,就像一般的参数一样,使得定义的类型通用性更强. 泛型的优势: 编译具有严格的类型检查 java编译器对于泛型代码的 ...

  9. Java基础---泛型、集合框架工具类:collections和Arrays

    第一讲     泛型(Generic) 一.概述 1.JDK1.5版本以后出现的新特性.用于解决安全问题,是一个类型安全机制. 2.JDK1.5的集合类希望在定义集合时,明确表明你要向集合中装入那种类 ...

  10. Java基础——泛型

    一.定义 泛型(generic)是指参数化类型的能力.可以定义带泛型类型的类或方法,随后编译器会用具体的类型来替换它(泛型实例化).使用泛型的主要优点是能够在编译时,而不是在运行时检测出错误.它是jd ...

随机推荐

  1. FLEXNET License管理

    之前的程序License管理是我自己手撸的一个非常简单的东东,根据用户机器的MAC地址生成一个字串,程序执行的时候去比较这个字串.当时只是追求一个最简单的实现,像证书过期.功能点证书自然没有.这次新版 ...

  2. 如何在ASP.NET 5上搭建基于TypeScript的Angular2项目

    一.前言 就在上月,公司的一个同事建议当前的前端全面改用AngularJs进行开发,而我们采用的就是ASP.NET 5项目,原本我的计划是采用TypeScript直接进行Angular2开发.所以借用 ...

  3. 一次与51aspx客服MM谈话 -- 坑是怎么发展的

    GG从发布以来,我每次版本更新都会同步到51aspx源码网站,这次在同步更新GG V3.2版本到51aspx时,出了点小状况: 上传3.2版本几个小时后,我再次上去查看,发现其状态变成了“退回”,于是 ...

  4. 海量用户-高并发SAAS产品测试上线流程

    海量用户高并发SAAS产品测试上线流程 SAAS产品测试上线流程-以Web插件产品为例子 1   概述 在互联网产品中,IT公司之间更加注重产品功能之间的协作,SAAS形态的产品扮演着越来越重要的作用 ...

  5. var与this,{}与function 小记

    JavaScript var是用来定义一个变量,this常用来定义或调用一个属性或方法.但是在全局范围内,this和var定义变量是等价的. window console.log('window:', ...

  6. Ng Http Request/response格式转换

    angular作为Single Page Application推荐的交互方式当然是基于json的ajax调用.但今天要说的是当你不幸工作在一个遗留或者不可控制的服务上,而这服务是基于非json提交方 ...

  7. Nim教程【十】

    openarray类型 注意:openarray类型只能用于参数 固定大小的数组虽然性能不错,但过于呆板,使用取来不是很方便 对于一个方法来说,传入参数如果是一个数组,最好是不要限制数组的长度 也就是 ...

  8. 用 C 扩展 python

    本文介绍如何用 C 语言来扩展 python.所举的例子是,为 python 添加一个设置字符串到 windows 的剪切板(Clipboard)的功能.我在写以下代码的时候用到的环境是:window ...

  9. [Java面试四]Strust2总结及在面试中的一些问题.

    1. JavaEE软件三层结构和MVC的区别? JavaEE软件三层机构是由sun公司提供JavaEE开发规范的:Web层(表现层).业务逻辑层.数据持久层.[其中WEB层会使用前端控制器模式] MV ...

  10. Thinking in java中关于Exception的一道面试题.

    今天看到Thinking in Java中一个关于Exception的例子:最后看到有一篇总结的比较好的文章, 这里拿来记录下, 文章地址是:http://blog.csdn.net/salerzha ...