Vishrant
Vishrant

Reputation: 16628

Java Case Sensitivity: Class file collision: A resource exists with a different case

I am in Windows OS, working in eclipse IDE, I have following two scenario:

1. I have created below class, this is in Employee.java class (E is in uppercase):

public class Employee {
    public static void main(String[] args) {
        employee emp = new employee();
        emp.test();
    }
}

//here e is in lowercase
class employee {
    public void test() {
        System.out.println("I am in test()");
    }
}

In this case I got below Exception:

Exception in thread "main" java.lang.NoClassDefFoundError: employee (wrong name: Employee)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(Unknown Source)
.
.
.
at Employee.main(Employee.java:4) // i.e at emp.test();

2. I have created below class, this is Employee.java class:

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

    }
}

Now when I tried to create employee.java (e is in lower case) class in same package, I got the message in eclipse that Type with same name but different case exists.

My question is: Java is case sensitive. Does this means JVM (windows and UNIX based) is case sensitive or the compiler is case sensitive? And why it gives that exception in scenario 1 and eclipse does not allow me to create employee.java file in same location in scenario 2.

Also remember I am on Windows OS which is case insensitive for file name, so I know that it will not allow employee.java and Employee.java in same location. Does this violate in any means Java case sensitivity?

Upvotes: 2

Views: 21529

Answers (5)

James Jithin
James Jithin

Reputation: 10565

I had this issue with a gradle project which contained multiple children projects and the sources were different. One of them had a class that read com.package.level1.Main and another one had com.package.level1.main.Util. When I ran gradle build for the entire project, it ran well from command line, but the red exclamation on Eclipse project was tough enough to solve. How got rid of this was to remove the auto Java compiling of source files for the project and set to use only gradle. Here is how it is:

  1. Go to Project Properties.
  2. Choose Builders from the left pane.
  3. Unselect Java Builder and keep only Gradle Project Builder.
  4. Apply and Close the properties.
  5. Delete the project from workspace. While deleting, choose the option not to delete the files from filesystem.
  6. Import the project back to Eclipse and you should be done.

Upvotes: 0

Joop Eggen
Joop Eggen

Reputation: 109547

The file system on Windows is not case-sensitive: Employee.class and employee.class cannot reside in the same directory.

Scenario 1 with both classes defined in the same java source: The compiler creating employee.class probably overwerites Employee.class or whatever.

Scenario 2 with separate java sources: Eclipse would not be able to create an employee.java in the same directory as Employee.java (under Windows file system). Hence someone in the past took care to handle the error user friendly.

Java assumes case-sensitive names.

You could take your sources to Linux, compile them to a .jar (a zip format, again case-sensitive). Then copy the jar to windows and execute it.

By the way, I think you have found a new way to obfuscating java source code, decompiling under Windows.


A related topic is using Unicode letters in class / file names. That touches different platforms, different canonical representations of Unicode (é as one or two Unicode code points), version control systems.

Elaboration: (for the interested)

The human character é has two representations in Unicode:

  • "\u00E9" - as one code point U+00E9, é;
  • "e\u0301" - as two code points, U+009B, letter e, plus combining diacritical mark U-0301, ´ (zero width accent).

Unfortunately different operating systems (I was told) use a different canonical representation. I once wanted to use the version control system hg but had to find out, their missing support for Linux/Windows interoperability.

Otherwise one could normalize to a canonical form with java.text.Normalizer.

So let's wait for:

class CaféMañanaFaçade

Upvotes: 2

Dave Newton
Dave Newton

Reputation: 160191

No, it doesn't; Java is case-sensitive, and that's all Java has control over–itself.

It cannot control your file system, the implementation of which might not respect Java policies.

Upvotes: 0

Ian Roberts
Ian Roberts

Reputation: 122364

This isn't a limitation of Java but of the Windows file system where you're trying to write the files. On a case-insensitive file system the compiler can't write both Employee.class and employee.class to disk because as far as the FS is concerned they are the same file.

If you could somehow do the compilation to a case-sensitive file system (e.g. on Linux) and then package the resulting class files into a JAR then you would be able to run from that JAR without error on Windows, as a ZIP file is able to contain two distinct entries whose names differ only in case.

Upvotes: 2

Gauthier JACQUES
Gauthier JACQUES

Reputation: 675

Anyway, by convention, class names should always start with an upper case.

This convention helps avoiding the problem you're describing.

Upvotes: 0

Related Questions