如果您不引用Java中的对象,如:myString.concat(“that”)

如果您不引用Java中的对象,如:myString.concat(“that”),java,string,reference,Java,String,Reference,我更喜欢编译时错误-为什么不是这样?当调用任何具有返回类型的方法而不提供返回类型时,同样的问题也可以应用于该方法 String myString = "this"; //string is immutable myString.concat(" that"); //a new object is created but not assigned to anything System.out.println(myString); //prints out "this" 可以在不提供用于保存返

我更喜欢编译时错误-为什么不是这样?当调用任何具有返回类型的方法而不提供返回类型时,同样的问题也可以应用于该方法

String myString = "this";
//string is immutable

myString.concat(" that");
//a new object is created but not assigned to anything

System.out.println(myString); //prints out "this"
可以在不提供用于保存返回类型的引用/变量的情况下调用:

public myObject doStuff(...whatever){
 //define my method
 return anObject;
}

将立即创建对象并符合垃圾收集的条件(即,它可能很快就会被垃圾收集)

这不是编译时错误的原因是,并非每个返回方法的方法都要求使用该返回值。有些方法仅因其副作用而被调用

一个很好的例子是:它返回一个
boolean
对象,但通常情况下,调用代码对该结果不感兴趣,只是忽略它


类似地,返回
StringBuilder
实例,以便可以链接调用。但是忽略返回值并简单地使用
myStringBuilder.append(“foo”)

基本上,Java在方法定义头中没有内置机制,这些机制会告诉JVM该方法只对不可变数据有效,而该方法的唯一目的是输出数据


我想他们可以创建这样一种语言结构,但它会毫无意义地扰乱语言,而不会给我带来很多实际好处。

与其问它为什么要编译,不如想想它为什么不应该编译。你能想出任何借口吗?在这种情况下,警告确实是合适的。@Ingo:这样的警告会产生大量的误报。使用findbug工具:
…忽略String的返回值。concat(String)
@BoltClock,因为你永远不能引用连接的字符串,对meThis来说似乎是违反直觉的,它可以作为注释实现:
@Sideeffect
可以表示有(预期)副作用的方法,因此忽略它们的结果是可以的
@PureFunction
可以用于忽略结果会产生无效操作的情况。然后IDE/compiler/FindBugs可以分析这些注释(类似于在此类工具中使用
@NonNull
)。只有编译器或其他开发工具才应该使用这些信息,这对运行时环境并不重要。Joachim-你不能信任PureFunction注释,也不能证明或反驳它的真实性,因此,这样的注释几乎一文不值。@Ingo:我不同意:你不需要像证明
@NonNull
那样证明它:如果它是错误的,那么它就是库中的一个简单错误,就像任何其他错误一样。它仍然会增加很多价值。比较
@NonNull
注释:如果您的代码库始终使用此注释(以及相关的@Nullable),那么代码分析器可以提供有关可能的
NullPointerException
情况和不必要的null检查的非常好的信息。形式验证是从这个简单的方法中大大增加了复杂性,并且增加的相对较少(相对于复杂性)。Joachim-那么我们将不得不同意不同意。现在,生产代码中每天都会发生NullPointerException,根本没有办法系统地处理这些“库中的简单bug”。因此,形式化验证对IMHO来说是非常有价值的,顺便说一句,这会使整个代码分析器变得多余,因为它们试图告诉您编译器应该能够告诉您的东西。Joachim,您当然是正确的,但这暴露了java/API设计的另一个弱点。不可能区分因副作用而调用的方法和(或多或少纯粹的)功能,即。方法调用它们的返回值。如果有这样的话,当值未被使用时,确实可以发出有用的警告。@Ingo:请告诉我:哪种语言没有这种“弱点”?C、C++、C、Python、所有基本的变体和其他一些语言也是一样的。我能想到的唯一没有这个“问题”的语言是纯函数语言,其他情况(有副作用的方法/单子)变得非常复杂。
MyObject newObject = doStuff(); //works
doStuff(); //works too without assigning return object