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. SSH 动态端口forwarding是如何工作的

    好久没有来了,实在是太懒. 经常用SSH的动态端口forwarding 来FQ,使用像这样的命令: ssh -D 9999 -f -C -q -N sshHost.somewhere.com 这个命令 ...

  2. 说说WeakReference弱引用

    WeakReference弱引用概述 http://www.cnblogs.com/xrq730/p/4836700.html,关于Java的四种引用状态具体请参看此文 Java里一个对象obj被创建 ...

  3. 【读书笔记】Programming Entity Framework CodeFirst -- 初步认识

    以下是书<Programming Entity Framework Code First>的学习整理,主要是一个整体梳理. 一.模型属性映射约定 1.通过 System.Component ...

  4. python 模块加载

    python 模块加载 本文主要介绍python模块加载的过程. module的组成 所有的module都是由对象和对象之间的关系组成. type和object python中所有的东西都是对象,分为 ...

  5. [异常解决] MPU6050启动异常读出陀螺仪和加速度计的值全为0的解决办法

    在调试一个自己做的手环,每次用keil烧写好程序运行的蓝牙.陀螺仪都是正常的.但是掉电再上电之后蓝牙是好的.陀螺仪可以读出ID但是读出的加速度和角速度数据全为0. 下面是发生问题时main函数的前面部 ...

  6. 更改Photoshop 语言为英语(无需语言包)

    因为有时看国外教程时,手头上的PS是中文的而教程里的界面是英文的,而且中英菜单顺序在某些地方是不一样的,所以很不方便. 终于找到一个非常完美的方法可以把界面换成英文,而且不需任何语言包. 并且试了在最 ...

  7. 在 Win10 命令行使用 Consolas + 微软雅黑

    这个过程挺神奇的,步骤参考了下面两篇文章,但是过程很曲折: 1. 使用Monaco和微软雅黑字体美化cmd和PowerShell 2. [zz]Windows的cmd.exe使用consolas加中文 ...

  8. Redis学习笔记~分布式的Pub/Sub模式

    回到目录 redis的客户端有很多,这次用它的pub/sub发布与订阅我选择了StackExchange.Redis,发布与订阅大家应该很清楚了,首先一个订阅者,订阅一个服务,服务执行一些处理程序(可 ...

  9. 知方可补不足~SqlServer自动备份数据库及清理备份文件

    回到目录 对于SQLSERVER这个关系型数据库来说,为了保持数据的安全,备份是必须的,当你的一个误操作导致数据丢失,这可能是灾难性的,是不被允许发生的,这时,我们必须要做好定期的备份工作,如我们可以 ...

  10. 22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表。然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法showB输出大写的英文字母表。最后编写主类C,在主类的main方法 中测试类A与类B。

    22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表.然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法sh ...