您的位置 首页 java

你不知道的Java系列,这几件事你一定要知道!

程序员最重要的是思想,知其然知其所以然。

作为尚学堂的一员小编想问,你从一开始就在使用 java 吗?你是否还记得Java被称作为”Oak”的时期?那时,面向对象仍然是一个热门的话题,使用C++的人们都认为Java没有任何机会,Applets 也只是一件事情。

重载 仅返回类型不同的方法

这样的代码无法编译,对不?

class Test {

Object x() { return “abc”; }

String x() { return “123”; }

}

对。 Java 语言不允许两个方法在同一个类中“等效重载”,而忽略其诸如 throws 自居或返回类型等的潜在的差异。

查看 Class.getMethod(String, Class…) 的 Javadoc。 其中说明如下:

请注意,类中可能有多个匹配方法,因为 Java 语言禁止在一个类声明具有相同签名但返回类型不同的多个方法,但 Java 虚拟机 并不是如此。虚拟机中增加的灵活性可以用于实现各种语言特征。例如,可以用 桥接 方法实现协变参返回; 桥接方法和被重写的方法将具有相同的签名但拥有不同的返回类型。

哇哦,有道理。实际上下面的代码暗藏着很多事情:

abstract class Parent<T> {

abstract T x();

}

class Child extends Parent<String> {

@ Override

String x() { return “abc”; }

}

来看看为 Child 生成的字节码:

// Method descriptor #15 ()Ljava/ lang /String;

// Stack: 1, Locals: 1

java.lang.String x();

0 ldc </String><String “abc”> [16]

2 areturn

Line numbers:

[pc: 0, line: 7]

Local variable table:

[pc: 0, pc: 3] local: this index: 0 type: Child

// Method descriptor #18 ()Ljava/lang/Object;

// Stack: 1, Locals: 1

bridge synthetic java.lang.Object x();

0 aload_0 [this]

1 invokevirtual Child.x() : java.lang.String [19]

4 areturn

Line numbers:

[pc: 0, line: 1]

其实在字节码中 T 真的只是 Object。这很好理解。

合成的桥方法实际是由编译器生成的,因为 Parent.x() 签名中的返回类型在实际调用的时候正好是 Object。在没有这种桥方法的情况下引入 泛型 将无法在二进制下兼容。因此,改变 JVM 来允许这个特性所带来的痛苦会更小(副作用是允许协变凌驾于一切之上) 很聪明,不是吗?

Target Type 目标类型

Java Compiler 会根据你指定的目标类型来推断(infers)出method该返回哪种类型的结果,例如:

Collections.emptyList

static <T> List<T> emptyList(); //这个方法没有参数,只有一个T类型的返回类型,那么我不能传入参数这个方法是如何知道用什么返回类型的呢,这就是target type

List<String> listOne = Collections.emptyList();

listOne是一个List<String>类型的变量,Java Compiler会根据这个目标类型来推断出emptyList method应该返回这个类型,这种类型推断依赖于assignment context,也就是说我要赋给哪个变量,它是什么类型我就返回什么类型。

一句话总结就是:Java 恰好是一种看起来神秘的语言,其实不然。

文章来源:智云一二三科技

文章标题:你不知道的Java系列,这几件事你一定要知道!

文章地址:https://www.zhihuclub.com/197719.shtml

关于作者: 智云科技

热门文章

网站地图