应该返回false的用户输入返回true-问答-阿里云开发者社区-阿里云

开发者社区> 问答> 正文

应该返回false的用户输入返回true

被纵养的懒猫 2019-10-09 17:50:08 66

到目前为止,我一直在程序中使用运算符比较所有字符串。但是,我遇到了一个错误,将其中一个更改为错误.equals(),并修复了该错误。

true==false?什么时候应该使用它,不应该使用它?有什么不同?

同样很高兴知道,如果您覆盖.equals()方法,请确保您覆盖.hashcode()方法,否则最终将违反等价关系b / w equals和hashcode。有关更多信息,请参阅Java文档。 留下我对为什么==在对象上起作用的解释的链接:stackoverflow.com/a/19966154/2284641 ==有时会工作,因为java有一个String池,在这里它尝试重用常用字符串的内存引用。但是==比较一下,对象是相等的,而不是值。。。那么.equals()您想使用的正确用法就是。 – James Oravec 除非您喜欢追踪细微的错误并研究Java String Interning过程的复杂性,否则切勿使用==来测试String是否相同。"12"=="1"+2是错误的(可能) –

== 测试引用是否相等(它们是否是同一对象)。

.equals() 测试值是否相等(在逻辑上是否为“相等”)。

Objects.equals()null在调用之前进行检查,.equals()因此您不必(在JDK7起可用,在Guava中也可用)。

String.contentEquals()将的内容String与任何内容进行比较CharSequence(从Java 1.5开始可用)。

因此,如果要测试两个字符串是否具有相同的值,则可能要使用Objects.equals()。

// These two have the same value new String("test").equals("test") // --> true

// ... but they are not the same object new String("test") == "test" // --> false

// ... neither are these new String("test") == new String("test") // --> false

// ... but these are because literals are interned by // the compiler and thus refer to the same object "test" == "test" // --> true

// ... string literals are concatenated by the compiler // and the results are interned. "test" == "te" + "st" // --> true

// ... but you should really just call Objects.equals() Objects.equals("test", new String("test")) // --> true Objects.equals(null, "test") // --> false Objects.equals(null, null) // --> true 您几乎总是想使用Objects.equals()。在极少数情况下,您知道要处理实习生字符串,可以使用==。

从JLS 3.10.5起。字符串文字:

而且,字符串文字总是引用class 的相同实例String。这是因为使用方法将字符串文字(或更广泛地说,是常量表达式的值的字符串(第15.28节))“ 插入 ”以便共享唯一的实例String.intern。

在JLS 3.10.5-1中也可以找到类似的示例。

==测试对象引用,.equals()测试字符串值。

有时看起来好像在==比较值,因为Java进行了一些后台操作,以确保相同的内联字符串实际上是同一对象。

例如:

String fooString1 = new String("foo"); String fooString2 = new String("foo");

// Evaluates to false fooString1 == fooString2;

// Evaluates to true fooString1.equals(fooString2);

// Evaluates to true, because Java uses the same object "bar" == "bar"; 但要注意空值!

==可以null很好地处理字符串,但是.equals()从空字符串调用将导致异常:

String nullString1 = null; String nullString2 = null;

// Evaluates to true System.out.print(nullString1 == nullString2);

// Throws a NullPointerException System.out.print(nullString1.equals(nullString2)); 因此,如果您知道该值fooString1可能为空,请告诉读者

System.out.print(fooString1 != null && fooString1.equals("bar")); 以下内容比较简短,但检查空值(来自Java 7)不太明显:

System.out.print(Objects.equals(fooString1, "bar"));

有时看起来好像“ ==”比较值, - == 一定要比较值!(只是某些值是参考!) is,没有isNullOrEmpty()的静态方法,也没有运算符的自定义重载,这使得Java的这一部分比C#或Python笨拙。而且由于Java没有扩展方法,因此您无法编写自己的实用程序来扩展java.lang.String。对?关于将String子类化,添加该静态实用程序方法,然后始终使用MyString的任何想法?带有两个参数以进行空安全比较的静态方法也可以在该子类中使用。 – Jon Coombs 2014年 6月20日下午1:00 7 Groovy使用安全导航操作符(groovy.codehaus.org/…),使此操作变得容易一些?.。那将转换nullString1?.equals(nullString2);为一个完全为空的语句。但是,如果有帮助,它validString?.equals(nullString);仍然没有帮助-仍然会引发异常。 :短方法在Java中为空的比较字符串stackoverflow.com/questions/11271554/...

@JonCoombs Java支持子类化和创建自己的方法。但是由于某些原因,很少有类被标记为final,String是其中之一,因此我们无法扩展。我们可以在其中创建其他类并制作实用程序类,该类以两个字符串作为参数,并在那里实现我们的逻辑。同样,对于null检查其他一些库(例如spring和apache),也可以使用该库

== 比较对象引用。

.equals() 比较字符串值。

有时==会产生比较String值的错觉,例如以下情况:

String a="Test"; String b="Test"; if(a==b) ===> true 这是因为当您创建任何String文字时,JVM首先在String池中搜索该文字,并且如果找到匹配项,则将对新String赋予相同的引用。因此,我们得到:

(a == b)===>是

                   String Pool
 b -----------------> "test" <-----------------a

但是,==在以下情况下失败:

String a="test"; String b=new String("test"); if (a==b) ===> false 在这种情况下,new String("test")将在堆上创建语句new String,并将对该引用进行引用b,因此b将在堆上(而不是在String池中)为其提供引用。

现在a指向字符串池中的字符串,而b指向堆上的字符串。因此,我们得到:

if(a == b)===>否。

            String Pool
 "test" <-------------------- a

               Heap
 "test" <-------------------- b

虽然.equals()总是比较String的值,所以在两种情况下它都为true:

String a="Test"; String b="Test"; if(a.equals(b)) ===> true

String a="test"; String b=new String("test"); if(a.equals(b)) ===> true 因此使用.equals()总是更好。

.equals()比较两个实例,但是实现了equals来比较它们。那可能比较或不比较toString的输出。

@Jacob对象类.equals()方法比较实例(引用/地址),其中String类.equals()方法被覆盖以比较内容(字符)

很好地指出字符串池与Java堆的差异,因为它们肯定是不相同的。在字符串池中的Java试图“缓存” String的对象,以节省内存占用为String被称为是不可变的(我希望,我说这里正确)。还要检查

该==运营商检查是否两个字符串是完全相同的对象。

该.equals()方法将检查两个字符串是否具有相同的值。

通常,我强烈建议apache commons库:commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/…,java.lang.String) –

Java中的字符串是不可变的。这意味着每当您尝试更改/修改字符串时,您都会获得一个新实例。您不能更改原始字符串。这样做是为了可以缓存这些字符串实例。典型的程序包含许多字符串引用,对这些实例进行缓存可以减少内存占用并提高程序性能。

当使用==运算符进行字符串比较时,您不是在比较字符串的内容,而是在实际上比较内存地址。如果它们相等,则返回true和false。而equals in string比较字符串内容。

所以问题是,如果所有字符串都缓存在系统中,为什么==返回false,而返回true?好吧,这是可能的。如果像String str = new String("Testing")创建新字符串一样,即使缓存中已经包含具有相同内容的字符串,最终还是会在缓存中创建新字符串。总之"MyString" == new String("MyString")总会返回false。

Java还讨论了可以在字符串上使用以使其成为高速缓存一部分的函数intern(),因此"MyString" == new String("MyString").intern()将返回true。

注意:==运算符比等于运算符快得多,因为您正在比较两个内存地址,但是您需要确保代码没有在代码中创建新的String实例。否则,您将遇到错误。

String a = new String("foo"); String b = new String("foo"); System.out.println(a == b); // prints false System.out.println(a.equals(b)); // prints true 确保您了解原因。这是因为==比较只比较引用;该equals()方法对内容进行逐字符比较。

当您为a和调用new时b,每个引用都会获得一个新的引用,该引用指向"foo"字符串表中的。引用不同,但是内容相同。

==表示您的两个字符串引用是完全相同的对象。您可能已经听说过这种情况,因为Java保留了某种文字表(它确实这样做了),但并非总是如此。某些字符串以不同的方式加载,它们是由其他字符串等构成的,因此,您绝不能假定两个相同的字符串存储在同一位置。

等于为您做真正的比较。

是的,==对于比较字符串(任何对象,除非您知道它们是规范的)都是不利的。 ==只是比较对象引用。 .equals()测试是否相等。对于字符串,通常它们是相同的,但是正如您所发现的,并不能保证总是如此。

分享改善这个答案 14年12月17日于8:28编辑 社区维基 2转,2位用户使用67% cletus 添加评论

115

Java有一个String池,Java在该池下管理String对象的内存分配。请参见Java中的字符串池

使用==运算符检查(比较)两个对象时,会将地址相等性比较到字符串池中。如果两个String对象具有相同的地址引用,则返回true,否则返回false。但是,如果要比较两个String对象的内容,则必须重写该equals方法。

equals 实际上是Object类的方法,但是它被重写为String类,并给出了一个新的定义来比较对象的内容。

Example: stringObjectOne.equals(stringObjectTwo); 但是请注意,它尊重String的大小写。如果要区分大小写,则必须使用String类的equalsIgnoreCase方法。

让我们来看看:

String one = "HELLO"; String two = "HELLO"; String three = new String("HELLO"); String four = "hello";

one == two; // TRUE one == three; // FALSE one == four; // FALSE

one.equals(two); // TRUE one.equals(three); // TRUE one.equals(four); // FALSE one.equalsIgnoreCase(four); // TRUE 分享改善这个答案 18年2月8日于19:19编辑 社区维基 4转,3用户80% Saurabh Agarwal 6 我看到这是一个大问题的较晚答案。我可以问一下现有答案中没有提到的内容吗? – 他添加了@Mysticial equalsIgnoreCase,这可能对新手有帮助。

我同意zacherates的回答。

但是您可以做的是调用intern()非文字字符串。

从zacherates示例:

// ... but they are not the same object new String("test") == "test" ==> false 如果您实习非字面性的字符串相等是 true

new String("test").intern() == "test" ==> true

这通常不是一个好主意。实习相对昂贵,并且(反常地)会>>增加<<您的JVM的内存占用并增加GC成本。在大多数情况下,这些优势超过了==用于字符串比较的性能优势

==比较Java中的对象引用,对象也不例外String。

为了比较对象(包括String)的实际内容,必须使用equals方法。

如果使用来比较两个String对象,==结果是true,那是因为这些String对象已被检查,并且Java虚拟机有多个引用指向的同一实例String。不应期望将String包含相同内容的一个String对象==与用于评估为的另一个对象进行比较true。

.equals()比较类中的数据(假设函数已实现)。 ==比较指针位置(对象在内存中的位置)。

==如果两个对象(不讲主旨)都指向SAME对象实例,则返回true。 .equals()如果两个对象包含的数据与Java中的相同,则返回trueequals()==

那可能对您有帮助。

==执行引用相等性检查,检查这两个对象(在这种情况下为字符串)是否引用内存中的同一对象。

该equals()方法将检查两个对象的内容或状态是否相同。

显然==速度更快,但是如果您只想知道2 Strings 是否包含相同的文本,则在很多情况下(可能)会给出错误的结果。

绝对equals()推荐使用方法。

不用担心性能。鼓励使用的一些方法String.equals():

的执行String.equals()参考平等首先检查(使用==),并且如果2个字符串相同参考,不执行进一步的计算! 如果两个字符串引用不同,String.equals()则接下来将检查字符串的长度。这也是一种快速的操作,因为String该类存储字符串的长度,而无需计算字符或代码点。如果长度不同,则不执行进一步检查,我们知道它们不能相等。 只有到了这一步,才可以实际比较这两个字符串的内容,这只是一种速记比较:如果我们发现一个不匹配的字符(在两个字符串中的相同位置,则不是所有字符都将被比较) ),则不会再检查其他字符。 总而言之,即使我们保证字符串是实习生,使用该equals()方法仍然不是人们可能会想到的开销,绝对是推荐的方法。如果要进行有效的引用检查,请在语言规范和实现保证相同的枚举值是相同的对象的情况下使用枚举(通过引用)。

Obviously == is faster-实际上.equals(String)先执行==其他检查,然后说速度差不多。 public boolean equals(Object anObject) { if (this == anObject) { return true; } ...

如果您像我一样,当我刚开始使用Java时,我想使用“ ==”运算符来测试两个String实例是否相等,但是无论好坏,这都不是在Java中实现的正确方法。

在本教程中,我将演示几种正确地比较Java字符串的方法,从我通常使用的方法开始。在本Java字符串比较教程的最后,我还将讨论为什么在比较Java字符串时“ ==”运算符不起作用。

选项1:使用equals方法 对Java字符串进行比较大多数时候(可能是95%的时间),我将字符串与Java String类的equals方法进行比较,如下所示:

if (string1.equals(string2)) 此String equals方法查看两个Java字符串,如果它们包含完全相同的字符串,则认为它们相等。

让我们看一个使用equals方法的快速String比较示例,如果运行了以下测试,则两个字符串将不被视为相等,因为字符并不完全相同(字符的大小写不同):

String string1 = "foo"; String string2 = "FOO";

if (string1.equals(string2)) { // this line will not print because the // java string equals method returns false: System.out.println("The two strings are the same.") } 但是,当两个字符串包含完全相同的字符串时,equals方法将返回true,如以下示例所示:

String string1 = "foo"; String string2 = "foo";

// test for equality with the java string equals method if (string1.equals(string2)) { // this line WILL print System.out.println("The two strings are the same.") } 选项2:使用equalsIgnoreCase方法进行字符串比较

在某些字符串比较测试中,您将要忽略字符串是大写还是小写。当您要以不区分大小写的方式测试字符串是否相等时,请使用String类的equalsIgnoreCase方法,如下所示:

String string1 = "foo"; String string2 = "FOO";

// java string compare while ignoring case if (string1.equalsIgnoreCase(string2)) { // this line WILL print System.out.println("Ignoring case, the two strings are the same.") } 选项3:使用compareTo方法比较Java字符串

还有另一种比较不常见的比较Java字符串的方法,那就是使用String类的compareTo方法。如果两个字符串完全相同,则compareTo方法将返回值0(零)。以下是此字符串比较方法的简要示例:

String string1 = "foo bar"; String string2 = "foo bar";

// java string compare example if (string1.compareTo(string2) == 0) { // this line WILL print System.out.println("The two strings are the same.") } 当我写有关Java中的相等性的概念时,必须注意Java语言在基本Java Object类中包含equals方法。每当创建自己的对象时,只要想提供一种方法来查看对象的两个实例是否相等,就应该在类中重写(并实现)此equals方法(以Java语言提供的相同方式) String equals方法中的这种相等/比较行为)。

您可能需要看一下== 、. equals(),compareTo()和compare()

用于字符串文字,例如String string1 =“ foo bar”; 字符串string2 =“ foo bar”; 您可以直接使用==运算符来测试内容是否相等 – JAVA 2013年 9月7日,18:11 1个 在google apps脚本中,“ compareTo”不是可能的。我试着instaed“等于”这是唯一可行的解决方案.... -

功能:

public float simpleSimilarity(String u, String v) { String[] a = u.split(" "); String[] b = v.split(" ");

long correct = 0;
int minLen = Math.min(a.length, b.length);

for (int i = 0; i < minLen; i++) {
    String aa = a[i];
    String bb = b[i];
    int minWordLength = Math.min(aa.length(), bb.length());

    for (int j = 0; j < minWordLength; j++) {
        if (aa.charAt(j) == bb.charAt(j)) {
            correct++;
        }
    }
}

return (float) (((double) correct) / Math.max(u.length(), v.length()));

} 测试:

String a = "This is the first string.";

String b = "this is not 1st string!";

// for exact string comparison, use .equals

boolean exact = a.equals(b);

// For similarity check, there are libraries for this // Here I'll try a simple example I wrote

float similarity = simple_similarity(a,b);

这与其他答案有何不同?以及为什么按照您的建议进行 – @马克上的差异的问题==,并equals已经通过其他的解决办法回答,我只是提供了一个不同的方式在一个宽松的方式比较字符串 -

该==运营商检查,如果两个引用指向同一个对象或没有。.equals()检查实际的字符串内容(值)。

请注意,该.equals()方法属于类Object(所有类的超类)。您需要根据您的类要求重写它,但是对于String而言,它已经实现,并且它检查两个字符串是否具有相同的值。

情况1

String s1 = "Stack Overflow"; String s2 = "Stack Overflow"; s1 == s2; //true s1.equals(s2); //true 原因:不带空值创建的字符串文字存储在堆的permgen区域的字符串池中。因此s1和s2都指向池中的同一对象。

情况二

String s1 = new String("Stack Overflow"); String s2 = new String("Stack Overflow"); s1 == s2; //false s1.equals(s2); //true 原因:如果使用new关键字创建String对象,则会在堆上为其分配单独的空间。

==比较对象的参考值,而类中equals()存在的方法java.lang.String将String对象的内容(与另一个对象)进行比较。

不必挑剔,但是equals()for 的方法String实际上是在String类中,而不是在中Object。默认值equals()in Object不会比较内容是否相同,并且实际上在引用相同时仅返回true。

@JacobSchoen:由于GrepCode关闭,上述链接不再起作用。这是equals实现的替代方法:[内联链接](zgrepcode.com/java/openjdk/10.0.2/java.base/java/lang/…) – Amandeep Singh 1月27日在6:16

我认为定义a时就定义了String一个对象。所以你需要使用.equals()。当您使用原始数据类型时,必须==与String(以及任何对象)一起使用.equals()。

另请注意,==不适用于char [] – Khaled.K 13 Mar 24 '13 at 14:03 7 “ char []”不是原始数据类型!它是“ char”的数组。数组本身并不是原始数据类型。

如果该equals()方法存在于java.lang.Object类中,并且期望检查对象状态的等效性!也就是说,对象的内容。而==运营商预计将检查实际的对象实例是相同与否。

考虑两个不同的参考变量,str1以及str2:

str1 = new String("abc"); str2 = new String("abc"); 如果您使用 equals()

System.out.println((str1.equals(str2))?"TRUE":"FALSE"); 您将获得与TRUE使用一样的输出==。

System.out.println((str1==str2) ? "TRUE" : "FALSE"); 现在,您将获得FALSEas输出,因为str1和str2都指向两个不同的对象,即使它们都共享相同的字符串内容。这是因为new String()每次都会创建一个新对象。

运算符==始终用于对象引用比较,而String类.equals()方法被覆盖以进行内容比较:

String s1 = new String("abc"); String s2 = new String("abc"); System.out.println(s1 == s2); // It prints false (reference comparison) System.out.println(s1.equals(s2)); // It prints true (content comparison) 分享改善这个答案 18年2月8日于19:20编辑 社区维基 3转,2个用户, sham.y为54%

.equals()由于Object包含一个.equals()返回布尔值的方法,因此保证所有对象都具有一个方法。如果需要进一步定义,则子类的工作就是覆盖此方法。没有它(即使用==),仅检查两个对象之间的内存地址是否相等。字符串重写此.equals()方法,并且不使用内存地址,而是返回字符级别的字符串比较以确保相等。

一个重要的注意事项是,字符串存储在一个总池中,因此一旦创建了字符串,它将永远存储在同一地址的程序中。字符串不变,它们是不可变的。这就是为什么如果要处理大量的字符串时,使用常规的字符串连接是一个不好的主意的原因。相反,您将使用StringBuilder提供的类。请记住,指向此字符串的指针可以更改,并且如果您有兴趣查看两个指针是否相同的==话,这是一个很好的方法。字符串本身没有。

“一旦创建了字符串,它将永远存储在程序中的相同地址上” -这是绝对错误的。只有编译时常量字符串表达式(可能涉及final String变量)和程序显式实习的字符串才存储在所谓的“集总池”中。String一旦没有其他活动对象像其他任何类型的对象一样,所有其他对象也将进行垃圾回收。同样,虽然整个实习机制必须具备不变性,但与此无关。 –泰德·霍普 ( Ted Hopp)2014年4月10日在18:13 字符串比较是通过equals或equalsIgnoreCase方法完成的,该方法实际上是比较字符串的内容。但是==符号只是检查参考值。对于这种情况,来自字符串池的字符串文字可以正常工作。字符串s1 =新的String(“ a”); 字符串s2 =新的String(“ a”); 在这种情况下,s1 == s2为假,但s1.equals(s2)为真。 您也可以使用该compareTo()方法比较两个字符串。如果compareTo结果为0,则两个字符串相等,否则比较的字符串不相等。

在==比较了参考,不比较实际的字符串。如果确实使用创建了每个字符串,new String(somestring).intern()则可以使用==运算符比较两个字符串,否则只能使用equals()或compareTo方法。

在Java中,当使用“ ==”运算符比较两个对象时,它将检查对象是否指向内存中的同一位置。换句话说,它将检查两个对象名称是否基本上是对相同内存位置的引用。

Java String类实际上覆盖了Object类中默认的equals()实现,并且覆盖了该方法,以便它仅检查字符串的值,而不检查它们在内存中的位置。这意味着,如果调用equals()方法比较2个String对象,则只要实际字符序列相等,就认为这两个对象相等。

该==运营商的检查,如果两个字符串是完全相同的对象。

该.equals()方法检查两个字符串是否具有相同的值。

除非其中之一为null,否则如果s为null,则s.equals(s2)将崩溃,从而导致比较失败。当然,这并不与答案矛盾。这只是一个警告。 不,它不会崩溃,它将抛出NullPointerException,从而导致无法进行比较。

分享到
取消 提交回答
全部回答(0)
云计算
使用钉钉扫一扫加入圈子
+ 订阅

时时分享云计算技术内容,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。

推荐文章