泛型, String, 数组, 枚举, 注解

目录


类型信息

  1. 可以通过反射获取类运行时的类型信息 RTTI Class类
  2. 类字面常量 Test.class 加载 链接(在链接阶段将验证类中的字节码,为 static 字段分配存储空间,并且如果需要的话,将解析这个类创建的对其他类的所有引用) 初始化
    .class 语法来获得对类对象的引用不会引发初始化。但与此相反,使用 Class.forName() 来产生 Class 引用会立即就进行初始化(调用static,但不会调用构造函数)。如果一个 static final 值是“编译期常量”(如 Initable.staticFinal),那么这个值不需要对 Initable 类进行初始化就可以被读取,对 Initable.staticFinal2 的访问将强制进行类的初始化(调用static,但不会调用构造函数),因为它不是一个编译期常量
  3. 泛型
// Integer 继承自 Number。但事实却是不行,因为 Integer 的 Class 对象并不是 Number的 Class 对象的子类
Class<Number> geenericNumberClass = int.class;
// work 使用 Class<?> 的好处是它表示你并非是碰巧或者由于疏忽才使用了一个非具体的类引用,而是特意为之
Class<?> intClass = int.class;
intClass = double.class;
// 限制了
Class<? extends Number> bounded = int.class;
Class.isInstance() 方法提供了一种动态测试对象类型的方法。因此,所有这些繁琐的 instanceof
  1. RTTI 。RTTI 的含义所在:在运行时,识别一个对象的类型,接下来就是多态机制的事了,Shape 对象实际执行什么样的代码,是由引用所指向的具体对象(Circle、Square 或者 Triangle)决定的。使用 RTTI,我们可以查询某个 Shape 引用所指向对象的确切类型,然后选择或者剔除特例
  2. Java 是如何在运行时识别对象和类信息的。主要有两种方式:
  • “传统的” RTTI:假定我们在编译时已经知道了所有的类型;
  • “反射”机制:允许我们在运行时发现和使用类的信息。
  1. 如果基类来自别人的库,这时 RTTI 便是一种解决之道:可继承一个新类,然后添加你需要的方法。在代码的其它地方,可以检查你自己特定的类型,并调用你自己的方法

泛型

  1. ArrayList<String> 和 ArrayList<Integer> 在运行时实际上是相同的类型,它们都被擦除成原生类型 List。(擦除的核心动机是你可以在泛化的客户端上使用非泛型的类库)但是 String不能添加Integer,编译器就会报错。以下这个不会报错
GenericBase<T>
class Derived2 extends GenericBase {} // No warning
  1. 泛型的所有动作都发生在边界处——对入参的编译器检查和对返回值的转型。这有助于澄清对擦除的困惑,记住:“边界就是动作发生的地方”
  2. T[] array = new T[SIZE] 会报错(部分原因是由于擦除,部分原因是编译器无法验证 T 是否具有默认(无参)构造函数)
  3. 协变, 逆变
// 这里更多的是读取
Class<? extends Number> bounded = int.class;
// 如果不知道 List 中持有的对象是什么类型,你怎能保证安全地向其中添加对象呢, 只能加null
// 如果是T泛型就OK,因为知道具体类型 使用通配符可以将ArrayList<Apple>向上转型了,也就实现了协变
//List<? extends Number> x3 = new ArrayList<>();
// 超类通配符可以写入 这是逆变 这样编译器就知道向其中添加Apple或Apple的子类型(例如Jonathan)是安全的了
List<? super Number> x = new ArrayList<>();
Integer x1 = 3;
x.add(x1);
  1. class SelfBounded<T extends SelfBounded<T>>
    自限定所做的,就是要求在继承关系中,像下面这样使用这个类:
class A extends SelfBounded<A>{}

它可以保证类型参数必须与正在被定义的类相同

  1. 自限定类型的价值在于它们可以产生协变参数类型——方法参数类型会随子类而变化
class Base {}
class Derived extends Base {}

interface OrdinaryGetter {
    Base get();
}

interface DerivedGetter extends OrdinaryGetter {
    // Overridden method return type can vary: 协变
    @Override
    Derived get();
}

public class CovariantReturnTypes {
    void test(DerivedGetter d) {
        Derived d2 = d.get();
    }
}
  1. 泛型异常
interface Processor<T, E extends Exception> {
    void process(List<T> resultCollector) throws E;
}

String

  1. string+ 会被编译器优化成StringBuild append方法
  2. 不可变性体现在每次都返回一个新对象
  3. StringTokenizer可做分词用,有了正则和Scanner之后这个类基本不用

数组

  1. Arrays.copyOf原生数组和对象数组都可以被复制。但是,如果复制对象的数组,那么只复制引用—不复制对象本身。这称为浅拷贝。只复制了对象的引用(内存地址),并没有为每个元素新创建对象,虽然是个新数组。底层System.arraycopy()。
  2. System.arraycopy() ,它将一个数组复制到另一个已经分配的数组中。这将不会执行自动装箱或自动卸载—两个数组必须是完全相同的类型。System.arraycopy 对于数组是深拷贝,对于数组内的对象是浅拷贝。因为操作的传入参数是数组,那么回归本意,效果是深复制。
  3. Arrays.parallelSort(la) 并发排序
  4. 一旦数组被排序,您就可以通过使用 Arrays.binarySearch()
  5. Arrays parallelPrefix()。这类似于 Stream 类中的 reduce() 方法:它对前一个元素和当前元素执行一个操作,并将结果放入当前元素位置

枚举:

  1. 不能继承自一个 enum
  2. enum 都继承自 Java.lang.Enum 类。由于 Java 不支持多重继承,所以你的 enum 不能再继承其他类
  3. import static enums.AlarmPoints.*;可以简化操作
  4. EnumSet(Enum的set集合) 的基础是 long,一个 long 值有 64 位,而一个 enum 实例只需一位 bit 表示其是否存在。 也就是说,在不超过一个 long 的表达能力的情况下,你的 EnumSet 可以应用于最多不超过 64 个元素的 enum, EnumSet 可以应用于多过 64 个元素的 enum,所以我猜测,Enum 会在必要的时候增加一个 long
// public enum AlarmPoints
EnumSet<AlarmPoints> points = EnumSet.noneOf(AlarmPoints.class); // Empty
points.add(BATHROOM);

EnumSet是高性能的基于位运算

  1. EnumMap 是一种特殊的 Map,它要求其中的键(key)必须来自一个 enum,EnumMap速度很快
  2. 多路分发就是指在调用a.plus(b),a和b都不知道确切类型,也能让他们正常交互
    java实现多路分发

注解:

  1. @FunctionalInterface:Java 8 中加入用于表示类型声明为函数式接口
  2. 注解元信息
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {}
@Target 定义你的注解可以应用在哪里(例如是方法还是字段)
@Retention 定义了注解在哪里可用,在源代码中(SOURCE),class文件(CLASS)中或者是在运行时(RUNTIME)
@Documented 将此注解保存在 Javadoc 中
@Repeatable 允许一个注解可以被使用一次或者多次(Java 8)
  1. 反射处理注解
for(Method m : cl.getDeclaredMethods()) {
UseCase uc = m.getAnnotation(UseCase.class);
  1. aop加注解的形势
@Around("@annotation(****.common.annotation.PreventContinueClick)")
  1. 写注解时加default
String description() default ""
  1. 不能使用 extends 关键字来继承 @interfaces
  2. @Retention(RetentionPolicy.SOURCE)
    当你创建用于 javac 注解处理器时,你不能使用 Java 的反射特性,因为你处理的是源代码,而并非是编译后的 class 文件
  3. Javac 是一种编译器,能将一种语言规范转化成另外一种语言规范
  4. Javadoc用于描述类或者方法的作用

参考文章

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,744评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,505评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,105评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,242评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,269评论 6 389
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,215评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,096评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,939评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,354评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,573评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,745评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,448评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,048评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,683评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,838评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,776评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,652评论 2 354