11

I was tracking down a bug today, and I noticed something strange within one of our classes. I cut out as much code as possible to post here:

class A {
    static int obtainNumber() { return 42; }
    static int obtainNumber() { return 3; }
    static int obtainNumber() { return -1; }
    static {
        System.out.println(obtainNumber());
    }
}

This class has 3 methods with the exact same name and signature. At first I thought this was invalid code, but then eclipse would have highlighted the code in red. It does work:

javac A.java && java A
42
Exception in thread "main" java.lang.NoSuchMethodError: main

So I figured maybe Java will just use the first one it sees. I reordered to test:

class A {
    static int obtainNumber() { return 3; }
    static int obtainNumber() { return -1; }
    static int obtainNumber() { return 42; }
    static {
        System.out.println(obtainNumber());
    }
}

Nope, same result:

javac A.java && java A
42
Exception in thread "main" java.lang.NoSuchMethodError: main

I thought perhaps it uses the one with 42 because its the biggest. To test this, I took the original and changed the return values:

class A {
    static int obtainNumber() { return 0; }
    static int obtainNumber() { return 1; }
    static int obtainNumber() { return 2; }
    static {
        System.out.println(obtainNumber());
    }
}

It still knows to use the first one:

javac A.java && java A
0
Exception in thread "main" java.lang.NoSuchMethodError: main

And if I reorder them again:

class A {
    static int obtainNumber() { return 1; }
    static int obtainNumber() { return 0; }
    static int obtainNumber() { return 2; }
    static {
        System.out.println(obtainNumber());
    }
}

Same result:

javac A.java && java A
0
Exception in thread "main" java.lang.NoSuchMethodError: main

I thought Java was a text based language, which I'd expect makes this sort of thing impossible. How is Java tracking which method is which?

Dog
  • 7,707
  • 8
  • 40
  • 74
  • 1
    If you notice, the one that is taken is the one with the different syntax hiliting from the others. Perhaps that may clue you in based on hidden characters or grammar quirks. – nanofarad Jul 15 '13 at 20:03
  • 1
    Why would someone do this? It's like a magic trick played on the programmer – jamesSampica Jul 15 '13 at 20:10
  • @Jim from Batman The Dark Knight: *Some men just want to watch the world burn*. – Luiggi Mendoza Jul 15 '13 at 20:11
  • 1
    So many bad ideas have just spawned in me because of this – chancea Jul 15 '13 at 20:14
  • You should check the project for encoding issues, especially if it has been recovered from other system types or older storage media that may be faulty or have been exposed to legacy equipment that carries the plague. – nanofarad Jul 15 '13 at 20:14

3 Answers3

8

I just copied/pasted this in my IDE and though it was a miracle, then when trying to save the file an error message appeared clearing this issue:

Save could not be complete. Try File > Save As... if the problem persists.

Reason: Some characters cannot be mapped using "Cp1252" caracter encoding. Either change the encoding or remove the characters which are not supported by the "Cp1252" caracter encoding.

So, these methods don't have the same name, just use characters that look the same.

More info related to character encoding on Java source files:

Community
  • 1
  • 1
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
6

Hidden characters. The source code is equivalent to

static int obtainNumber() { return 42; }

static int obtain\ufeffNumber() { return 3; }

static int obtain\ufeff\ufeffNumber() { return -1; }

To avoid this kind of problems, my source files are strictly US-ASCII. I want to be certain that the characters I see are exactly the characters compiler sees.

ZhongYu
  • 19,446
  • 5
  • 33
  • 61
1

My original comment:

If you notice, the one that is taken is the one with the different syntax hiliting from the others. Perhaps that may clue you in based on hidden characters or grammar quirks.

I pasted this into Eclipse, and noticed a little extra character. I threw my saved file(in CP1252) into a hex editor, and found a byte order mark.

When I looked, CP1252 doesn't have a byte order mark, yet the characters are themselves in CP1252. A stray unicode character may have entered.

When I looked more closely, another method had another byte order mark in another byte order.

How they came to be, we'll never know. However, we do know that the compiler is taking the one without the byte order mark.

You should check the project for encoding issues, especially if it has been recovered from other system types or older storage media that may be faulty or have been exposed to legacy equipment.

We really need to deal with this FGITW behavior via meta sometime now.

nanofarad
  • 40,330
  • 4
  • 86
  • 117