Java编程思想:擦除的补偿(数组泛型处,我有很多细节没有研究)
import sun.net.www.content.text.Generic;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Test {
public static void main(String[] args) {
// ClassTypeCapture.test();
// InstantiateGenericType.test();
CreatorGeneric.test();
}
}
/*
15.8 擦除的补偿
——标记下,这个地方乱七八糟,我有点混乱
因为擦除的问题,我们有时候必须通过引入类型标签来对擦除进行补偿。这意味
着你需要显式地传递你的类型的Class对象,以便你可以在类型表达式中使用它。
在前面的例子中对instanceof的尝试最终失败了,因为其类型信息已经被擦除了。
如果引入类型便签,就可以转而使用动态的isInstance()。(前面的失败完全是
因为非要将一个具体类型标签符给一个没有指明的类型标签)
*/
class Building { }
class House extends Building { }
class ClassTypeCapture<T>{
Class<T> kind;
public ClassTypeCapture(Class<T> kind){
this.kind=kind;
}
public boolean f(Object arg) {
/*
这个地方应该涉及到了Class对象储存信息方面的问题
*/
return kind.isInstance(arg);
}
public static void test() {
// ClassTypeCapture<Building> ctt1 = new ClassTypeCapture<>(Building.class);
// System.out.println("ctt1.f(new Building()):"+ctt1.f(new Building()));
// System.out.println("ctt1.f(new House()):"+ctt1.f(new House()));
//
// System.out.println();
ClassTypeCapture<House> ctt2 = new ClassTypeCapture<>(House.class);
System.out.println("ctt2.f(new Building()):"+ctt2.f(new Building()));
System.out.println("ctt2.f(new House()):"+ctt2.f(new House()));
}
}
/*
我把上一个案例的代码,和解读贴在这儿,帮助我理解一下这个问题:
即使kind被存储为Class<T>,擦除也就意味着它实际将被存储为Class,没有任何参数。
因此当你在使用它时,例如在创建数组时,Array.newInstance()实际上并未拥有kind
所蕴含的类型信息,因此这不会产生具体的结果,所以必须转型,这将产生一条令你无法满
意的警告。
*/
class ArrayMaker<T>{
//运行时实际保存的是Class<Object>
private Class<T> kind;
public ArrayMaker(Class<T> kind) {
//这个地方在运行时,把一个Class<T>赋给了Class<Object>
this.kind=kind;
}
@SuppressWarnings("unckecked")
T[] create(int size) {
return (T[]) Array.newInstance(kind,size);
}
public static void test() {
ArrayMaker<String> s = new ArrayMaker<>(String.class);
String[] stringArray = s.create();
// System.out.println(Arrays.toString(stringArray));
}
}
/*
15.8.1 创建类型实例
需求:
解决在在泛型类中不能用T t创建对象的方案。Java中可以传递一个工厂对象,并使用它来
创建新的实例。最便利的工厂对象就是Class对象,因此如果使用类型标签,那么你可以使用
newInstance()来创建这个类型的新对象。
*/
class ClassAsFactory<T>{
T x;
T y;
Class<T> k;
public ClassAsFactory(Class<T> kind) {
try{
x = kind.newInstance(); //这个地方没有将kind对象存给任何被擦除了的对象哦
System.out.println("x:"+x.getClass().getName());
/*
很奇怪,我这儿并有发生前文描述的任何问题?
*/
k=kind;
y = k.newInstance();
System.out.println("y:"+y.getClass().getName());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
class Employee { }
//这个方案由于问题不是在编译期报出来,故不推荐
class InstantiateGenericType {
static void test() {
new ClassAsFactory<Employee>(Employee.class);
System.out.println("ClassAsFactory<Employee> succeeded");
//
// ClassAsFactory<Integer> f1 =
// new ClassAsFactory<>(Integer.class);
}
}
//Sun建议使用的显式工厂
interface Factory<T>{
T create();
}
class Foo2<T>{
private T x;
public <F extends Factory<T>> Foo2(F factory){
x = factory.create();
}
}
class IntegerFactory implements Factory<Integer>{
@Override
public Integer create() {
);
}
}
/*
这个为什么会报错啊!!!
class Widget{
//嵌套类实现一个工厂,但是报错了,说是循环实现
static class Factory implements Factory<Widget>{
public Widget create() {
return new Widget();
}
}
}
*/
class FactoryConstraint{
static void test() {
new Foo2<Integer>(new IntegerFactory());
// new Foo2<Widget>(new Widget.Factory());
}
}
/*
最后一种在泛型类中实例参数对象的方法:使用模板方法设计模式。
*/
abstract class GenericWithCreate<T>{
final T element;
GenericWithCreate(){
element=create();
}
abstract T create();
}
class X{}
class Creator extends GenericWithCreate<X>{
@Override
X create() {
return new X();
}
void f(){
System.out.println(element.getClass().getSimpleName());
}
}
class CreatorGeneric{
static void test() {
Creator c = new Creator();
c.f();
}
}
/*
最后做一个自己的实验,验证一下现在真的不可以在泛型类中创建参数化对象么?
*/
class A<T>{
T t;
A(){
//t = new T(); 果然不可以
}
}
/*
15.8.2 泛型数组
——这部分东西,我暂时不研究了,很枯燥,而且感觉价值并不是太高
解决不能创建泛型数组的方案:在任何想要创建泛型数组的地方都使用ArrayList
*/
class ListOfGenerics<T>{
private List<T> array = new ArrayList<>();
public void add(T item){array.add(item);}
public T get(int index){return array.get(index);}
}
/*
有时,你仍旧希望创建泛型类型的数组(例如,ArrayList内部使用的是数组)。有趣的是
你可以按照编译器喜欢的方式来定义一个引用,例如:
*/
class H<T> {}
class ArrayOfH{
static H<Integer>[] gia;
}
/*
编译器接受这个程序,而不会产生任何警告。但是,永远都不能创建这个确切类型的数组(包括
参数类型),因此这有点令人困惑。既然所有数组无论它们持有的类型如何,都具有相同的结构
(每个数组槽位的尺寸和数组的布局),那么看起来你应该能够创建一个Object数组,并将其
装换成所希望的数组类型。事实上这可以编译,但是不能运行,它将产生ClassCaseException
*/
class ArrayOfGeneric{
;
static H<Integer>[] gia;
@SuppressWarnings("unchecked")
static void test() {
gia = (H<Integer>[])new H[SIZE];
}
}
/*
成功创建泛型数组的唯一方式就是,创建一个被擦除类型的新数组,然后对其转型
*/
Java编程思想:擦除的补偿(数组泛型处,我有很多细节没有研究)的更多相关文章
- Java编程思想学习(十二) 数组和容器
一.数组 1).数组的多种初始化方式 下面总结了初始化数组的多种方式,以及如何对指向数组的引用赋值,使其指向另一个数组对象.值得注意的是:对象数组和普通数组的各种操作基本上都是一样的:要说有什么不同的 ...
- Java中的泛型 --- Java 编程思想
前言 我一直都认为泛型是程序语言设计中一个非常基础,重要的概念,Java 中的泛型到底是怎么样的,为什么会有泛型,泛型怎么发展出来的.通透理解泛型是学好基础里面中非常重要的.于是,我对<Ja ...
- 《Java编程思想》第一二章
前段时间一直通过网络教程学习Java基础,把面向对象部分学完之后本来打算继续深入学习,但是感觉自己操之过急了,基础根本不够扎实,所以入手了一本<Java编程思想>,希望先把基础打好,再深入 ...
- Java编程思想—八皇后问题(数组法、堆栈法)
Java编程思想-八皇后问题(数组法.堆栈法) 实验题目:回溯法实验(八皇后问题) 实验目的: 实验要求: 实验内容: (1)问题描述 (2)实验步骤: 数组法: 堆栈法: 算法伪代码: 实验结果: ...
- Java编程思想(11~17)
[注:此博客旨在从<Java编程思想>这本书的目录结构上来检验自己的Java基础知识,只为笔记之用] 第十一章 持有对象 11.1 泛型和类型安全的容器>eg: List<St ...
- JAVA编程思想——分析阅读
需要源码.JDK1.6 .编码风格参考阿里java规约 7/12开始 有点意识到自己喜欢理论大而泛的模糊知识的学习,而不喜欢实践和细节的打磨,是因为粗心浮躁导致的么? cron表达式使用 设计能力.领 ...
- Java编程思想 笔记
date: 2019-09-06 15:10:00 updated: 2019-09-24 08:30:00 Java编程思想 笔记 1. 四类访问权限修饰词 \ 类内部 本包 子类 其他包 publ ...
- 《Java编程思想》读书笔记(二)
三年之前就买了<Java编程思想>这本书,但是到现在为止都还没有好好看过这本书,这次希望能够坚持通读完整本书并整理好自己的读书笔记,上一篇文章是记录的第一章到第十章的内容,这一次记录的是第 ...
- Java编程思想 (1~10)
[注:此博客旨在从<Java编程思想>这本书的目录结构上来检验自己的Java基础知识,只为笔记之用] 第一章 对象导论 1.万物皆对象2.程序就是对象的集合3.每个对象都是由其它对象所构成 ...
- Java 编程思想 Chapter_14 类型信息
本章内容绕不开一个名词:RTTI(Run-time Type Identification) 运行时期的类型识别 知乎上有人推断作者是从C++中引入这个概念的,反正也无所谓,理解并能串联本章知识才是最 ...
随机推荐
- ThreadPoolExecutor的一点理解 专题
corePoolSize(maxActiveThreadSize):线程池大小,决定着新提交的任务是新开线程云执行还是放到任务队列中,也是线程池的最最核心的参数.一般线程池开始时是没有线程的,只有当任 ...
- WPF Build Action
None: The file is not included in the project output group and is not compiled in the build process. ...
- Web性能优化分析
如果你的网站在1000ms内加载完成,那么会有平均一个用户停留下来.2014年,平均网页的大小是1.9MB.看下图了解更多统计信息. 直击现场 <HTML开发MacOSApp教程> ht ...
- ZooKeeper+Dubbo+SpringBoot 微服务Demo搭建
1. 首先创建springBoot项目,springBoot是一堆组件的集合,在pom文件中对需要的组件进行配置.生成如下目录结构 创建test项目,同步在test创建dubbo-api,dubbo- ...
- 原生Js封装的产品图片360度展示
挺简单的一段程序,但是效果不错: 1.把需要展示的36张图片先预加载到浏览器缓存里 2.给展示图片的div添加方法 3.通过鼠标左右移动的像素转换图片 在线效果预览:http://jsfiddle.n ...
- 基于ASP.NET的新闻管理系统(一)
1. 项目简介 1.1设计内容 (1)可以在首页查看各类新闻,可以点击新闻查看具体内容:可以查看不同类型的新闻,并了解热点新闻,可以在搜索框里输入要查找的内容. (2)在后台界面中,管理员可以修改密码 ...
- js中prototype与__proto__区别
proto(隐式原型)与prototype(显式原型) 显式原型 explicit prototype property:每一个函数在创建之后都会拥有一个名为prototype的属性,这个属性指向函数 ...
- C语言实现常用数据结构——二叉树
#include<stdio.h> #include<stdlib.h> #define SIZE 10 typedef struct Tree { int data; str ...
- echarts 中国地图标注所在点
达到的效果: 1.本身是个中国地图‘ 2.直接通过经纬度标注 3.标注点可以是其他样子(比如:五角星) 4.标注点具有提示框并且鼠标可以进入 5.提示框里的链接可点击(可以添加为链接事件): 所需要技 ...
- sql一关联多查询时否定筛选出现的问题的解决
问题:一方关联多方查询时执行否定筛选,结果包含未通过筛选的项. 我们规定一方为父,多方为子,我们希望子未通过筛选时,结果也不出现对应的父. 查询部门及部门下的所有员工. SELECT * FROM d ...