技术标签: java
* 擦除的问题
* 为什么要擦除: 1.5版本才出现泛型 为了兼容之前地代码
* 它使得泛化的客户端可以用非泛化的类库来使用。
* 以及不破坏现有类库的情况下,将泛型融入java语言。
* 擦除使得现有的非泛型客户端代码能够在不改变的情况继续使用,直至客户端准备号用泛型重写这些代码。
* 擦除的代价:泛型不能用于显示地引用运行时类型的操作值中,例如转型instanceof操作和new表达式。
* 因为所有关于参数的类型都丢失了。无论何时,当你在编写泛型代码时,必须时刻提醒自己,
* 你只是看起来好像拥有关于参数的类型信息而已。提醒自己:T 不,它值时一个Object
* 擦除使用泛型并不是强制的
package com.zghw.base.generic;
import java.util.*;
/**
* 擦除的问题
* 为什么要擦除: 1.5版本才出现泛型 为了兼容之前地代码
* 它使得泛化的客户端可以用非泛化的类库来使用。
* 以及不破坏现有类库的情况下,将泛型融入java语言。
* 擦除使得现有的非泛型客户端代码能够在不改变的情况继续使用,直至客户端准备号用泛型重写这些代码。
* 擦除的代价:泛型不能用于显示地引用运行时类型的操作值中,例如转型instanceof操作和new表达式。
* 因为所有关于参数的类型都丢失了。无论何时,当你在编写泛型代码时,必须时刻提醒自己,
* 你只是看起来好像拥有关于参数的类型信息而已。提醒自己:T 不,它值时一个Object
* 擦除使用泛型并不是强制的
* @author zghw
*
*/
class Frob{}
class Fnorkle{}
class Quark<Q>{}
class Particle<POSITION,MOMENTUM>{}
public class ErasedTypeEquivalence {
/**
* ArrayList<String>和ArrayList<Integer>很容易认为是不同的类型,
* 不同的类型在行为方面肯定不同 但输出发现c1==c2为true
* @param args
*/
public static void main(String[] args) {
Class c1=new ArrayList<String>().getClass();
Class c2=new ArrayList<Integer>().getClass();
System.out.println(c1==c2);//输出为true
List<Frob> list = new ArrayList<Frob>();
Map<Frob,Fnorkle> map = new HashMap<Frob,Fnorkle>();
Quark<Fnorkle> quark = new Quark<Fnorkle>();
Particle<Long,Double> part=new Particle<Long,Double>();
//Class.getTypeParameters()将返回一个Typeariable对象数组,表示有泛型声明
//的类型参数...
System.out.println(Arrays.toString(list.getClass().getTypeParameters()));
System.out.println(Arrays.toString(map.getClass().getTypeParameters()));
System.out.println(Arrays.toString(quark.getClass().getTypeParameters()));
System.out.println(Arrays.toString(part.getClass().getTypeParameters()));
/**
* 输出结果:
* [E]
[K, V]
[Q]
[POSITION, MOMENTUM]
*/
/**
* 输出结果是一些占位符
* 说明:在泛型代码内部,无法获得任何有关泛型参数类型的信息。
* 当你在使用泛型时,任何具体的类型信息都被擦除了,你唯一知道的就是你在使用一个对象。
* 因此,List<String>和List<Integer>在运行时事实上是相同的类型。这两种形式都被
* 擦除成它们的原生类型,即List
*/
}
}
package com.zghw.base.generic;
/**
* 擦除带来的问题
* 1.无法创建类型实例
* 2.无法使用instanceof
* 3.无法调用类型实例方法
* 解决办法
* 通过引入类型标签来对擦除进行补偿。这意味着你需要显示地传递你地类型地Class对象,
* 以便你可以在类型表达式中使用它。
* 可以使用?extends T 继承来实现可以调用方法
* @author zghw
*/
class Erased<T>{
public static void f(Object arg){
//if(arg instanceof T){}//Error无法使用instanceof
//T var = new T();//Error无法创建类型实例
}
}
class Building {}
class House extends Building{}
public class ClassTypeCapture<T> {
Class<T> kind;
T t ;
public ClassTypeCapture(Class<T> kind){
this.kind = kind;
try {
t=kind.newInstance();//创建类型实例
} catch (Exception e) {
throw new RuntimeException();
}
}
public boolean isInstance(Object arg){
return kind.isInstance(arg);
}
public static void main(String[] args) {
ClassTypeCapture<Building> c1=new ClassTypeCapture<Building>(Building.class);
ClassTypeCapture<House> c2=new ClassTypeCapture<House>(House.class);
System.out.println(c1.isInstance(c2));
System.out.println(c1.isInstance(new Building()));
System.out.println(c1.isInstance(new House()));
System.out.println(c2.isInstance(new Building()));
System.out.println(c2.isInstance(new House()));
}
}
package com.zghw.base.generic;
/**
* 使用简单工厂来创建泛型T 建议创建泛型对象使用此方法
*
* @author zghw
*
*/
interface Factory<T> {
T creat();
}
class IntegerGen implements Factory<Integer> {
@Override
public Integer creat() {
return new Integer(0);// 由于Integer没有默认构造方法,无法使用Class创建泛型实例
}
}
class Widget {
public static class FactoryInner implements Factory<Widget> {
@Override
public Widget creat() {
return new Widget();
}
}
}
class Foo<T> {
private T x;
public <F extends Factory<T>> Foo(F factory) {
x = factory.creat();
}
public T get() {
return x;
}
}
public class FactoryConstraint {
public static void main(String[] args) {
Integer i = new Foo<Integer>(new IntegerGen()).get();
Widget w = new Foo<Widget>(new Widget.FactoryInner()).get();
}
}
package com.zghw.base.generic;
/**
* 使用模板方法创建泛型实例
*
* @author zghw
*
*/
abstract class GenericWithCreator<T> {
final T element;
public GenericWithCreator() {
element = creat();
}
abstract T creat();
}
class Obj {
}
class Creator extends GenericWithCreator<Obj> {
@Override
Obj creat() {
return new Obj();
}
void f() {
System.out.println(element.getClass().getSimpleName());
}
}
public class CreatorGeneric {
public static void main(String[] args) {
new Creator().f();
}
}
package com.zghw.base.generic;
import java.awt.Color;
/**
* 边界 边界作用: 可以用于在泛型地参数上设置限制条件。
* 你可以按照自己的边界类型来调用方法。
* 因为擦除移除了类型,所以你可以用泛型参数调用的方法只是Object调用的方法。
* 但是,如果能够将这个参数限制在某个类型子类,那么你就可以用这些类型子集来调用方法。
* 为了执行这种限制,Java泛型重用了extends关键字
*
* @author zghw
*
*/
interface HasColor {
Color getColor();
}
class Dimension {
public int x, y, z;
}
interface Weight {
int weight();
}
class HoldItem<T> {
T item;
HoldItem(T item) {
this.item = item;
}
T getItem() {
return item;
}
}
class Colored<T extends HasColor> {
T item;
Colored(T item) {
this.item = item;
}
Color getColor() {
return item.getColor();
}
}
class Colored2<T extends HasColor> extends HoldItem<T> {
Colored2(T item) {
super(item);
}
Color getColor() {
return item.getColor();
}
}
class ColoredDimension<T extends Dimension & HasColor> {
T item;
ColoredDimension(T item) {
this.item = item;
}
Color getColor() {
return item.getColor();
}
int getX() {
return item.x;
}
int getY() {
return item.y;
}
int getZ() {
return item.z;
}
}
class ColoredDimension2<T extends Dimension & HasColor> extends Colored2<T> {
ColoredDimension2(T item) {
super(item);
}
int getX() {
return item.x;
}
int getY() {
return item.y;
}
int getZ() {
return item.z;
}
}
class Solid2<T extends Dimension & HasColor & Weight> extends
ColoredDimension2<T> {
Solid2(T item) {
super(item);
}
int weight() {
return item.weight();
}
}
class Solid<T extends Dimension & HasColor & Weight> {
T item;
Solid(T item) {
this.item = item;
}
Color getColor() {
return item.getColor();
}
int getX() {
return item.x;
}
int getY() {
return item.y;
}
int getZ() {
return item.z;
}
int weight() {
return item.weight();
}
}
class Bounded extends Dimension implements HasColor, Weight {
@Override
public int weight() {
return 0;
}
@Override
public Color getColor() {
return null;
}
}
public class BasicBounds {
public static void main(String args[]) {
Solid<Bounded> s = new Solid<Bounded>(new Bounded());
Solid2<Bounded> s2 = new Solid2<Bounded>(new Bounded());
s.getColor();
s.getX();
s2.getColor();
s2.getY();
}
}
package com.zghw.base.generic;
/**
* 只有当你希望使用的类型参数比某个具体类型(以及它的所有子类型)更加“泛化”时--也就是说,当你希望
* 代码能够跨多个类工作时,时用泛型才有所帮助,通常比简单的类替换要更复杂
* 必须查看所有的代码,并确定它是否“足够复杂”到必须时用泛型的程度
* @author zghw
*
*/
class HasF{
void f(){
System.out.println();
}
}
class Manipulator<T>{
private T obj;
public Manipulator(T obj){
this.obj =obj;
}
public void set(T obj){
this.obj = obj;
}
public T get(){
return obj;
}
}
//没有泛型的类 比较上面的泛型类 可以发现泛型并没有任何好处
//T擦除了HasF,就好像在类的声明中用HasF一样
class Manipulator1{
private HasF obj;
public Manipulator1(HasF obj){
this.obj =obj;
}
public void set(HasF obj){
this.obj = obj;
}
public HasF get(){
return obj;
}
}
public class Manipulation {
public static void main(String[] args) {
Manipulator<HasF> m = new Manipulator<HasF>(new HasF());
Manipulator1 m1 = new Manipulator1(new HasF());
//T擦除了HasF,就好像在类的声明中用HasF一样
}
}
package com.zghw.base.generic;
import java.util.*;
/**
* 通配符
* 为什么需要通配符?
* 泛型没有内建的协变类型
* 通配符
* 1.? extends T 用作方法返回值 意味着 它可以是任何事物包括子类,而编译器无法验证“任何事物”的安全性
* 2.? super T 用作方法参数 将一个T类型的对象或者从T导出的任何对象作为参数传入使用类型的方法
* 3.?
* 因此你可能会根据如何能够向一个泛型类型”写入“(传递给一个方法),
* 以及如何能够从一个泛型类型中“读取”(从一个方法中返回),来左手思考子类型和超类型边界。
* @author zghw
*
*/
class Fruit{}
class Apple extends Fruit{}
class Jonathan extends Apple{}
class Orange extends Fruit{}
public class Covariance{
public static void main(String[] args) {
List<Fruit> list1 =new ArrayList<Fruit>();
List<Apple> list2 =new ArrayList<Apple>();
//编译不通过 Apple的List在类型上不等价于Fruit的List,即使Apple是Fruit的子类
//我们在讨论的是容器的类型,而不是容器持有的类型
//但是,我们想要在两个类型之间建立某种类型的向上转型关系,
//就需要通配符
//List<Fruit> list3 =new ArrayList<Apple>();//编译不通过
//List<? extends Fruit> :你可以读作”具有任何从Fruit继承的类型的列表“
//但List不会持有任何类型的Fruit. list3引用没有指定具体的类型
//只是为了向上转型
List<? extends Fruit> list3 =new ArrayList<Apple>();
//只接受 add(? extends Fruit e) 不了解到底需要Fruit的那个具有子类型
//因此它不会接受任何Fruit,甚至只接受null
//? extends Fruit 意味着 它可以是任何事物,而编译器无法验证“任何事物”的安全性
//list3.add(new Apple());//编译不通过
//list3.add(new Fruit());//编译不通过
//list3.add(new Object());//编译不通过
list3.add(null);
writeTo(new ArrayList<Fruit>(),new Apple());
}
/**
* ? super T 只作用泛型参数中,List将持有从T导出的某种具体类型,这样就可以安全的将一个T类型的对象
*或者从T导出的任何对象作为参数给List方法
* @param fruit
* @param item
*/
static <T> void writeTo(List<? super T> fruit,T item){
fruit.add(item);
}
}
package com.zghw.base.generic;
import java.util.*;
/**
* 通配符 ? extends T ? super T 的应用
*
* @author zghw
*
*/
public class GenericWriterReader {
static <T> void writeExact(List<T> list, T item) {
list.add(item);
}
static <T> void writeWild(List<? super T> list, T item) {
list.add(item);
}
static <T> T readExact(List<T> list) {
return list.get(0);
}
static class Reader<T> {
static <T> T readExact(List<T> list) {
return list.get(0);
}
}
static class ReadWild<T> {
static <T> T readExact(List<? extends T> list) {
return list.get(0);
}
}
static List<Fruit> fruitsw = new ArrayList<Fruit>();
static List<Apple> applesw = new ArrayList<Apple>();
static List<Fruit> fruits = Arrays.asList(new Fruit());
static List<Apple> apples = Arrays.asList(new Apple());
static void w1() {
writeExact(applesw, new Apple());
writeExact(fruitsw, new Apple());
}
static void w2() {
writeWild(applesw, new Apple());
writeWild(fruitsw, new Apple());
}
static void r1() {
Apple a = readExact(apples);
Fruit f = readExact(fruits);
f = readExact(apples);
}
static void r2() {
Reader<Fruit> r = new Reader<Fruit>();
Apple a = r.readExact(apples);
Fruit f = r.readExact(fruits);
f = r.readExact(apples);
}
static void r3() {
ReadWild<Fruit> r = new ReadWild<Fruit>();
Apple a = r.readExact(apples);
Fruit f = r.readExact(fruits);
f = r.readExact(apples);
}
public static void main(String[] args) {
w1();
w2();
r1();
r2();
r3();
}
}
文章浏览阅读556次,点赞2次,收藏3次。由于工作上的需要,今天捣鼓了半天高德地图。如果定制化开发需求不太高的话,可以用vue-amap,这个我就不多说了,详细就看官网 https://elemefe.github.io/vue-amap/#/zh-cn/introduction/install然而我们公司需要英文版的高德,我看vue-amap中好像没有这方面的配置,而且还有一些其他的定制化开发需求,然后就只用原生的高德。其实原生的引入也不复杂,但是有几个坑要填一下。1. index.html注意,引入的高德js一定要放在头部而_前端引入原生地图
文章浏览阅读104次。本文介绍ViewGroup重写,我们所熟知的LinearLayout,RelativeLayout,FrameLayout等等,所有的容器类都是ViewGroup的子类,ViewGroup又继承View。我们在熟练应用这些现成的系统布局的时候可能有时候就不能满足我们自己的需求了,这是我们就要自己重写一个容器来实现效果。ViewGroup重写可以达到各种效果,下面写一个简单的重写一个Vi..._viewgroup 重写
文章浏览阅读1.8w次,点赞279次,收藏1.5k次。本文章主要记录本人在学习stm32过程中的笔记,也插入了不少的例程代码,方便到时候CV。绝大多数内容为本人手写,小部分来自stm32官方的中文参考手册以及网上其他文章;代码部分大多来自江科大和正点原子的例程,注释是我自己添加;配图来自江科大/正点原子/中文参考手册。笔记内容都是平时自己一点点添加,不知不觉都已经这么长了。其实每一个标题其实都可以发一篇,但是这样搞太琐碎了,所以还是就这样吧。_stm32笔记
文章浏览阅读1.8k次。Android o CTS 测试之Media相关测试failed 小结(一)CTSCTS 即兼容性测试套件,CTS 在桌面设备上运行,并直接在连接的设备或模拟器上执行测试用例。CTS 是一套单元测试,旨在集成到工程师构建设备的日常工作流程(例如通过连续构建系统)中。其目的是尽早发现不兼容性,并确保软件在整个开发过程中保持兼容性。CTS 是一个自动化测试工具,其中包括两个主要软件组件:CTS tra..._mediacodec框架 cts
文章浏览阅读4.5k次。官网:https://harvesthq.github.io/chosen/实例化$(".chosen-select").chosen({disable_search_threshold: 10});赋值var optValue = $(".chosen-select").val();回显1.设置回显的值$(".chosen-select").val(“opt1”);2.触发cho..._chosen.js
文章浏览阅读1.9k次。撸码不易,网上找不到,索性自己写,且撸且珍惜!void bitsWrite(uint8_t* buff, int pos, int size, uint32_t value){ uint32_t index[] = { 0x80000000, 0x40000000, 0x20000000, 0x10000000, 0x8000000, 0x4000000, 0x2000000, 0x1000000, 0x800000, 0x400000, 0_unit8_t 集合 赋值 c++
文章浏览阅读748次。javaweb知识点_javaweb框架图
文章浏览阅读1.1w次,点赞3次,收藏16次。adb是没有自动升级的命令的,如果想要更新adb的版本,我们可以在网上找到自己想要的版本进行更新给大家提供几个版本https://pan.baidu.com/s/1yd0dsmWn5CK08MlyuubR7g&shfl=shareset 提取码: 94z81、下载解压后我们可以找到下面几个文件,并复制2、找到adb安装的文件夹下的platform-tools文件夹,我这里是..._adb iptabls怎么升级
文章浏览阅读3.8k次。很多用户可能都知道怎么在Windows系统上删除微信的聊天记录,那么苹果电脑上的微信软件怎么删除所有的聊天记录呢?下面小编就专门来给大家讲下微信mac版删除所有的聊天记录的图文教程。点击后会弹出提示窗口,点击这里的确认按钮就可以将其清理掉了。在这里选择要清理的数据,然后点击下方右边的清理按钮就行了。在mac上打开微信后,点击左下角的横线图标。然后再点击这里的管理微信聊天数据按钮。打开了设置窗口,点击上方的“通用”。在这里点击下方的前往清理按钮。点击弹出菜单里的“设置”。_mac微信怎么删除聊天列表
文章浏览阅读7.7k次。数据类型转换时报错:Request processing failed;nested exception is java.lang.NumberFormatException:For input String “20151512345”报错原因:数字格式异常,接着后面有 For input string: “201515612343” 提示,这就告诉我们你当前想把 “201515612343” 转换成数字类型时出错了。解决方案:使用2015151612343这个数字太大了,所以直接使用string_request processing failed; nested exception is java.lang.numberformatexcepti
文章浏览阅读387次。版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本文链接:https://blog.csdn.net/a844651990/article/details/78376767Qt qml 自定义消息提示框QtQuick有提供比较传统的信息提示框MessageDialog,但是实际开发过程并不太能满足我们的需求。下面是根据controls2模块中..._qml 自定义 messagedialog
文章浏览阅读599次。# Redis configuration file example.## Note that in order to read the configuration file, Redis must be# started with the file path as first argument:## ./redis-server /path/to/redis.conf # Note on units: when memory size is needed, it is pos._默认出厂的原始redis.conf文件全部内容