【问题标题】:The String class and Java's dependency on itString 类和 Java 对它的依赖
【发布时间】:2014-11-28 21:28:41
【问题描述】:

所以大家都知道,你能写的最短的Java程序是:

public class Program{
     public static void main(String []args){

     }
}

有人会怀疑这个最短的程序只包含语言关键字、选择的名称(如类名/函数名/参数名)和一些语法(括号等)。

但是当您仔细观察时,突然弹出 String 类。那么这是否意味着 Java 语言没有 String 类就无法生存?或者甚至没有完整的标准库? (我认为 C++ 可以在没有标准库的情况下存在,不是吗?)

我也一直在查看 String 类代码,但找不到运算符 + 和 += 的实现(也许其他可用?)。那么这是如何工作的呢?这是作为编译器中的特例嵌入的吗?哪个甚至会将 String 类更紧密地绑定到 java 语言?

在 Java 语言中是否还有其他类嵌入得如此之深?

【问题讨论】:

  • 首先,您对 String 数组的声明是错误的。将其编辑为:public static void main(String[] args)。这就是你如何在java中定义你的程序的入口点。其次,运算符 + 存在于 String 以及 += (这只是一种简短形式,而不是运算符本身)
  • Java 类有方法,它没有定义像 + 这样的操作符。
  • 虽然在 args 之前与 [] 一起工作,但在发布之前对其进行了测试,但这不是故意的,而是一个错字:)。我知道运算符存在于“您可以使用它们”中,但不存在于 String 类的代码中。
  • 如果没有 String,Java 将无法运行,因为 Object 中有一个 toString() 方法。
  • 请参阅docs.oracle.com/javase/specs/jls/se7/html/…,了解有关 + 运算符的 Java 7 规范详细信息。

标签: java string compiler-construction standard-library


【解决方案1】:

Java String 包含不可变的 Unicode 字符序列。 与 C/C++ 不同,其中字符串只是 chararray,Java 字符串是 java.lang 类的对象。

String 是 Java 中的特殊类,所有 String 字面量,例如 “abc”(双引号内的任何内容)都保存在单独的 字符串池,Java 内存中的特殊内存位置,更多 正好在PermGen Space里面。

任何时候你使用字符串字面量创建一个新的字符串对象,JVM 首先检查字符串池以及是否有类似内容的对象 可用,而不是返回它并且不创建新对象。 JVM 如果您使用 new 创建对象,则不执行字符串池检查 运算符。

不同于普通的类:

   String is associated with string literal in the form of double-quoted
   texts such as "Hello, world!". 

   You can assign a string literal directly into a String variable,
   instead of calling the constructor to create a String instance.

   The '+' operator is overloaded to concatenate two String operands.
   '+' does not work on any other objects such as your Person.java etc.

   String is immutable. That is, its content cannot be modified once it
   is created. For example, the method toUpperCase() constructs and
   returns a new String instead of modifying its existing content.

字符串在 Java 中得到特殊处理,因为它们在程序中经常使用。因此,效率(在计算和存储方面)至关重要。

Java 的设计者决定在面向对象的语言中保留原始类型,而不是让一切都成为对象,以提高语言的性能。

原语存储在调用堆栈中,这需要更少的存储空间并且操作起来更便宜。另一方面,对象存储在程序堆中,需要复杂的内存管理和更多的存储空间。

'+' 运算符,用于对基元(例如 int 和 double),被重载以对 String 对象进行操作。 '+' 对两个 String 操作数执行连接。 Java 不支持 考虑到软件工程的运算符重载 与 C++ 不同 您可以在其中转动“+”运算符来执行减法。

“+”运算符是唯一在内部重载以支持 Java 中的字符串连接的运算符。请注意,“+”不适用于任何两个任意对象。

JDK 编译器实际上同时使用 String 和 StringBuffer 来通过 '+' 运算符处理字符串连接。例如,

字符串 msg = "a" + "b" + "c";

为了提高效率会被编译成以下代码:

字符串消息 = 新 StringBuffer().append("a").append("b").append("c").toString();

出于性能原因,Java 的 String 被设计为介于原语和类之间。

【讨论】:

  • 不错的简历。 + 运算符是如何重载的?这是编译过程中的特殊处理吗?在源代码中找不到太多关于它的信息:grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
  • @Juru 我相信 + 运算符是由编译器实现的。由于它不是一种方法,因此您不太可能在 String 类本身中找到它。事实上,我只记得我最近读到编译器在看到 + 时生成使用 StringBuilder 的代码。
  • @Code-Apprentice 我编辑了这篇文章以包含有关编译器如何处理 + 的内容。
  • @Juru 我用一个例子将该部分添加到答案中。
  • 出于这个原因,有时(并非总是)最好使用 StringBuilder/Buffer 而不是“+”。例如考虑以下内容: "String a = ""; for (int i = 0; i
【解决方案2】:

Java Language Specification,第 1.4 节:

1.4。与预定义类和接口的关系

如上所述,本规范通常引用 Java SE 平台 API 的类。特别是,某些类与 Java 编程语言有着特殊的关系。示例包括诸如Object,Class,ClassLoader,String,Thread, 之类的类以及包java.lang.reflect 中的类和接口等。本规范限制了此类类和接口的行为,但没有为它们提供完整的规范。读者可参考 Java SE 平台 API 文档。

所以所有这些类都必须存在,否则它不会被视为标准 Java。

ObjectString 类分别由 4.3.24.3.3 部分更加充实。

4.3.2。班级Object

Object 类是所有其他类的超类(第 8.1.4 节)。

所有类和数组类型都继承(§8.4.8)类Object的方法,总结如下:

  • clone 方法用于复制对象。

  • equals 方法定义了对象相等的概念,它基于值,而不是引用,比较。

  • finalize 方法在对象被销毁之前运行(第 12.6 节)。

  • 方法getClass返回代表对象类的Class对象。

    每个引用类型都有一个Class 对象。例如,它可以用来发现一个类的完全限定名、它的成员、它的直接超类以及它实现的任何接口。

    getClass 的方法调用表达式的类型是 Class<? extends |T|>,其中 T 是为 getClass 搜索的类或接口(第 15.12.1 节)。

  • 声明为 synchronized(第 8.4.3.6 节)的类方法在与类的 Class 对象关联的监视器上同步。

  • hashCode 方法非常有用,与equals 方法一起,在诸如java.util.Hashmap 这样的哈希表中。

  • wait,notify,notifyAll 方法用于使用线程进行并发编程(第 17.2 节)。

  • toString 方法返回对象的 String 表示。

4.3.3。班级String

String 类的实例表示 Unicode 代码点序列。

String 对象具有常量(不变)值。

字符串文字(第 3.10.5 节)是对 String 类实例的引用。

字符串连接运算符+(第15.18.1 节)在结果不是常量表达式(第15.28 节)时隐式创建一个新的String 对象。


另外考虑Throwable,没有它甚至不能编译try/catch语句(14.20):

用于表示异常参数类型的每个类类型必须是类ThrowableThrowable的子类,否则会发生编译时错误。

【讨论】:

    猜你喜欢
    • 2016-03-15
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-06
    • 1970-01-01
    相关资源
    最近更新 更多