1

I was going through API code i found this in JAVA Api

java.io.FilePermission.getMask(String actions) {
    int mask = NONE;

    // Null action valid?
    if (actions == null) {
        return mask;
    }
    // Check against use of constants (used heavily within the JDK)
    if (actions == SecurityConstants.FILE_READ_ACTION) {
        return READ;
    } else if (actions == SecurityConstants.FILE_WRITE_ACTION) {
        return WRITE;
    } else if (actions == SecurityConstants.FILE_EXECUTE_ACTION) {
        return EXECUTE;
    } else if (actions == SecurityConstants.FILE_DELETE_ACTION) {
        return DELETE;
    } else if (actions == SecurityConstants.FILE_READLINK_ACTION) {
        return READLINK;
    }
....
....
.....
}

can any one tell me why they have used '==' operator instead of .equlas() method. :?

Ashish Aggarwal
  • 3,018
  • 2
  • 23
  • 46
khushnood
  • 95
  • 1
  • 6
  • Type int is a primitive type, so == is enough – qwerty Mar 10 '14 at 06:44
  • 1
    What is `SecurityConstants`? An enum? (edit: doesn't look like it; indeed, this code will certainly fail) – fge Mar 10 '14 at 06:44
  • should be asked from author – Abimaran Kugathasan Mar 10 '14 at 06:46
  • Those constants are strings, and nothing will fail if those constants are used. – Markus Malkusch Mar 10 '14 at 06:46
  • 1
    possible duplicate of [How do I compare strings in Java?](http://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java) – K.C. Mar 10 '14 at 06:47
  • @fge This code will not certainly fail. Actually, it will generally succeed (in fact, it is [private in `FilePermissions`](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/io/FilePermission.java#FilePermission.getMask%28java.lang.String%29) and thus the internal implementation has full control over the values passed to that function, so it will *certainly* succeed). – Jason C Mar 10 '14 at 06:54
  • @JasonC OK, I see. That's risky code, though. – fge Mar 10 '14 at 07:07
  • @fge I agree. It's a special case, I guess. If you trace back through the code it's *all* private and package private stuff. I am surprised, though, that they don't clearly document that behavior in the method docs, even if it is internal. There's not even a note in a comment. Not sure why they didn't just use an `enum`, or even just dummy `Object` instances to avoid ambiguity. – Jason C Mar 10 '14 at 07:10

4 Answers4

4

It is because of String interning. What happens is that the compiler interns String literals in memory at compile time (this is done to save memory). When you compare string literals with ==, it will work because they are in the same memory location.

I would recommend you to read this answer, so you get the idea. Here is the example (from that answer) and its explanation (mine):

1  // These two have the same value
2  new String("test").equals("test") --> true
3   
4  // ... but they are not the same object
5  new String("test") == "test" --> false
6   
7  // ... neither are these
8  new String("test") == new String("test") --> false
9  
10 // ... but these are because literals are interned by 
11 // the compiler and thus refer to the same object
12 "test" == "test" --> true
13 
14 // concatenation of string literals happens at compile time,
15 // also resulting in the same object
16 "test" == "te" + "st" --> true
17 
18 // but .substring() is invoked at runtime, generating distinct objects
19 "test" == "!test".substring(1) --> false

Explanation:

Why does line 12 and 16 evaluate to true? Because of String interning. What happens in these cases is that the compiler interns String literals in memory at compile time (this is done to save memory). In line 12 and 16 the Stringliterals that are beign compared are in the same memory location, so the comparison with == operator returns true. However, this is not recommended unless you want better performance (comparing memory addresses is a lot “cheaper” than a loop) and you are sure that the Strings being compared are interned literals.

Remember that those SecurityConstants are strings.

Community
  • 1
  • 1
Christian Tapia
  • 33,620
  • 7
  • 56
  • 73
  • 2
    Did you verbatim copy [somebody else's answer](http://stackoverflow.com/a/513839/616460) from http://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java to your blog, then claim it as yours *and* spam a link to your blog here instead of linking to the appropriate SO question? – Jason C Mar 10 '14 at 06:59
  • @JasonC you are right, I forgot I to mention the *initial source*. Edited. But in fact, I didn't claim it as mine; I put a link to the answer in the blog. Also, I took the example, but the explanation is from my words. – Christian Tapia Mar 10 '14 at 07:01
2

That action should be one of those constants declared in SecurityConstants class, which already instantiated and passed to that method. So it doesn't matter whether we compare with equals() or ==.

Abimaran Kugathasan
  • 31,165
  • 11
  • 75
  • 105
  • I think they are sure that always the same instance will be passed, but in there API anyone can assigne new instance from java.io.FilePermission.FilePermission(String path, String actions); and that is public construtor, but for the performance perspective this is good. – khushnood Mar 10 '14 at 10:15
  • @Khushnood, `private static int getMask(String actions)` is a private method, so, It can't be used anybody other than the user. – Abimaran Kugathasan Mar 10 '14 at 10:17
  • but any one can use from the java.io.FilePermission.FilePermission(String path, String actions); constructor that is public.... – khushnood Mar 10 '14 at 12:06
0

This works as long as actions is 100% guaranteed to reference one of those constant instances. Note that Java pools string literals so it also works when comparing to the literal "something".

class Example {

    static final String VALUE1 = "something";
    static final String VALUE2 = "another";

    void example () {
        String v;
        v = VALUE1; assert(v == VALUE1);
        v = VALUE2; assert(v == VALUE2);
        v = "something"; assert(v == VALUE1);
        v = new String("something"); assert(v != VALUE1); // <- not equal!
    }

}
Jason C
  • 38,729
  • 14
  • 126
  • 182
0

In the JVM string constant pool essentially cache all string literals.Therefore the same object will remain in the memorry. SO JVM avoid creating a new string object each time a literal is declared, which could get very expensive very quickly. Because of this still we can use ==.

Normally == is used to compare two object references. for the string comparison better to sue the equals() method. but when it deals with constant String you can still use == . but it should be done only if you sure it uses for constants.

Niroshan Abayakoon
  • 913
  • 1
  • 10
  • 22