java泛型程序设计——泛型类的静态上下文中类型变量无效+不能抛出或捕获泛型类的实例

【0】README

0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 泛型类的静态上下文中类型变量无效+不能抛出或捕获泛型类的实例 的知识;


【1】泛型类的静态上下文中类型变量无效

1.1)不能在静态域或方法中引用类型变量:

public class Singleton<T>
{
    private static T single; // ERROR
    private static getSingle() // ERROR
    {}
}

1.2)因为类型擦除后, 只剩下 Singleton 类, 它只包含一个 singleInstance 域;


【2】不能抛出或捕获泛型类的实例

2.1)既不能抛出也不能捕获泛型类对象。 且泛型类扩展 Throwable 也是不合法的;

如, public class Problem<T> extends Exception {} // ERROR--can't extend Throwable
  • 2.1.1)catch 子句中不能使用类型变量, 以下方法不能通过编译:
public static <T extends Throwable> void dowork(Class<T> t)
{
    ...
    catch(T e) // ERROR--can't catch type variable
}
  • 2.1.2)不过, 在异常规范中适用类型变量是允许的,以下方法是合法的:
public static <T extends Throwable> void dowork(T t)  throws T // OK

2.2)Java 异常处理的一个基本原则是: 必须为所有已检查异常提供一个处理器。 不过可以利用泛型消除这个限制。 关键的方法如下:

@SuppressWarnings("unchecked")
public static <T extends Throwable> void throwAS(Throwable e) throws T
{
    throw (T)e;
}
  • 2.2.1)假设以上方法包含在 类 Block中, 如果调用 Block.《RuntimeException》throwAs(t); 编译器就会认为t 是一个未检查异常。
  • 2.2.2)以下代码会把所有异常都转换为 编译器所认为的未检查异常:
try
{     do work;    }
catch(Throwable t)
{ Block.<RuntimeException>throwAs(t); }
  • 2.2.3)吧以上代码添加到一个抽象类中。 用户可以覆盖body 方法来提供一个具体的动作。 调用toThread 时, 会得到Thread类的一个对象, 它的run 方法不会介意已检查异常;
public abstract class Block
{
    public abstract void body() throws Exception;
    public Thread toThread()
    {
        return new Thread()
        {
            public void run()
            {
                try{body();}
                catch(Throwable t)
                {Block.<RuntimeException>throwAs(t); }
            }
        }
    }
}
@SuppressWarnings("unchecked")  // 消除对已检查异常的检查
public static <T extends Throwable> void throwAs(Throwable e) throws T
{ throw (T)e ;}

2.3)看个荔枝: 以下程序运行了一个线程, 它会抛出一个 已检查 的异常;

public class Test
{
    public static void  main(String[] args)
    {
        new Block()
        {
            public void body() throws Exception
            {
                Scanner in = new Scanner(new File("ququqx"));
                while(in.hasNext())
                    System.Out.println(in.next());
            }
        }.toThread().start();
    }
}
  • 2.3.1)运行这个程序, 会得到一个 栈轨迹;
  • 2.3.2)这有什么意义呢 ? 正常情况下, 你必须捕获线程run方法中的所有已检查异常, 把它们包装到 未检查异常中, 因为run方法声明为 不抛出 任何已检查异常;
  • 2.3.3)不过在这里, 我们并没有做这种包装。 我们只是抛出异常, 并哄骗编译器,让它认为这不是已检查异常;

Conclusion)通过使用泛型类, 擦除和 @SuppressWarnings 标注, 就能消除 java 类型系统的部分基本限制;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值