Is Java Case-Sensitive

Case sensitivity of Java class names

  • Are there any guarantees about which classes are loadable by the bootstrap class loader in every JVM?

The core bits and pieces of the language, plus supporting implementation classes. Not guaranteed to include any class that you write. (The normal JVM loads your classes in a separate classloader from the bootstrap one, and in fact the normal bootstrap loader loads its classes out of a JAR normally, as this makes for more efficient deployment than a big old directory structure full of classes.)

  • If there are any guarantees, does the behavior in the example above violate the guarantee (i.e. is the behavior a bug)?
  • Is there any way to make "standard" JVMs load a and A simultaneously? Would writing a custom class loader work?

Java loads classes by mapping the full name of the class into a filename that is then searched for on the classpath. Thus testcase.a goes to testcase/a.class and testcase.A goes to testcase/A.class. Some filesystems mix these things up, and may serve the other up when one is asked for. Others get it right (in particular, the variant of the ZIP format used in JAR files is fully case-sensitive and portable). There is nothing that Java can do about this (though an IDE could handle it for you by keeping the .class files away from the native FS, I don't know if any actually do and the JDK's javac most certainly isn't that smart).

However that's not the only point to note here: class files know internally what class they are talking about. The absence of the expected class from the file just means that the load fails, leading to the NoClassDefFoundError you received. What you got was a problem (a mis-deployment in at least some sense) that was detected and dealt with robustly. Theoretically, you could build a classloader that could handle such things by keeping searching, but why bother? Putting the class files inside a JAR will fix things far more robustly; those are handled correctly.

More generally, if you're running into this problem for real a lot, take to doing production builds on a Unix with a case-sensitive filesystem (a CI system like Jenkins is recommended) and find which developers are naming classes with just case differences and make them stop as it is very confusing!

Is JAVA_OPTIONS boolean case sensitive?

This is the occasion when the difference between being a good programmer and being a good designer matters:

  • A good programmer will make sure that this parametrization (-Djava.net.preferIPv4Stack=True) works in the current environment: For example, if you are using Open JDK 15, you shall browse the source code and you will see that the class java.net.PlainSocketImpl, where that parameter is used, delegates on Boolean.parseBoolean, which does a case-insensitive parsing.

  • A good designer, instead, will make sure to set a parametrization such that will work on every environment (Open JDK, Oracle JDK, version 15, future versions, Windows, Linux, etc), by sticking to the public documentation, which states that only "true" or "false" (or absent) values must be used.

Summarizing: If you are using Open JDK 15, there is no difference between "True" or "true" values, but you cannot be sure that in future versions such difference will matter. I recommend you to stick to the docummented allowed values.

Why is the Java compiler (javac) case-insensitive when java (the interpreter) is case-sensitive?

The Windows filesystem is case-insensitive.

You cannot (sanely) find a case-sensitive file on a case-insensitive filesystem.

If you run javac on Linux with a case-sensitive filesystem, it will be case-sensitive.

Ignore case-sensitive methodName for getting a method of a Class in Java

Java is case sensitive, so there's no such built-in method. You could, however, implement it yourself by iterating over all the methods and checking their names and parameter types:

public List<Method> getMethodsIgnoreCase
(Class<?> clazz, String methodName, Class<?> paramType) {

return Arrays.stream(clazz.getMethods())
.filter(m -> m.getName().equalsIgnoreCase(methodName))
.filter(m -> m.getParameterTypes().length == 1)
.filter(m -> m.getParameterTypes()[0].equals(paramType))
.collect(Collectors.toList());
}

Note:
This method looks for a method with a single argument that matches the given type, to match the requirement in the OP. It can easily be generalized to receive a list/array of argument types though.

Java File exists Case sensitive .jpg and .JPG

So you want to get the real case sensitive names of files stored in your filesystem. Lets imaging we have the following paths:

  • on Linux: using ext4 (which is case sensitive) /testFolder/test.PnG
  • on Windows using NTFS (which is not case sensitive) c:\testFolder\test.PnG

Now lets create some Java File Objects to each Image File.

// on Linux
File f1 = new File("/testFolder/test.png");
File f2 = new File("/testFolder/test.PNG");
File f3 = new File("/testFolder/test.PnG");
f1.exists(); // false
f2.exists(); // false
f3.exists(); // true

// on Windows
File f1 = new File("c:\\testFolder\\test.png");
File f2 = new File("c:\\testFolder\\test.PNG");
File f3 = new File("c:\\testFolder\\test.PnG");
f1.exists(); // true
f2.exists(); // true
f3.exists(); // true

Your problem is that all calls of File like File.exists are redirected to the java.io.FileSystem class that represents real Operating System calls of your File System by the JVM. So you cannot distinguish on Windows Machines between test.PNG and test.png. Neither do Windows itself.

But even on Windows each File has a defined name in the File System that could be for example: test.PnG. You will see this in your Windows Explorer or in Command Line if you type dir c:\testFolder.

So what you can do in Java is use the File.list method on the parent directory that results in the Operating System list call for all files in this directory with their real names.

File dir = new File("c://testFolder//");
for(String fileName : dir.list())
System.out.println(fileName);
// OUTPUT: test.PnG

or if you prefer File Objects

File dir = new File("c://testFolder//");
for(File file : dir.listFiles())
System.out.println(file.getName());
// OUTPUT: test.PnG

You can use this to write your own exists Method that is case sensitive on all operating systems

public boolean exists(File dir, String filename){
String[] files = dir.list();
for(String file : files)
if(file.equals(filename))
return true;
return false;
}

Use it like this:

File dir = new File("c:\\testFolder\\");
exists(dir, "test.png"); // false
exists(dir, "test.PNG"); // false
exists(dir, "test.PnG"); // true


EDIT: I have to admit that I was wrong. There is a way to get the real name of a File. I always overlooked the method File.getCanonicalPath.

Again our example: We have that File c:\testFolder\test.PnG.

File f = new File("c://testFolder//test.png");
System.out.println(f.getCanonicalPath());
// OUTPUT: C:\testFolder\test.PnG

With that knowledge you can write a simple test method for the case sensitive extension without iterating all files.

public boolean checkExtensionCaseSensitive(File _file, String _extension) throws IOException{
String canonicalPath = _file.getCanonicalPath();
String extension = "";
int i = canonicalPath.lastIndexOf('.');
if (i > 0) {
extension = canonicalPath.substring(i+1);
if(extension.equals(_extension))
return true;
}
return false;
}

Use it like this:

File f = new File("c://testFolder//test.png");    
checkExtensionCaseSensitive(f, "png"); // false
checkExtensionCaseSensitive(f, "PNG"); // false
checkExtensionCaseSensitive(f, "PnG"); // true

Case insensitive matching in Java switch-case statement

If you want to do that: just make sure the input data is in all lowercase, and use lowercase cases...

switch ("UPPER".toLowerCase()) {
case "upper" :

....

Localization issues

Also, the ages old issue of localization strikes again, and plagues this thing too... For example, in the Turkish Locale, the uppercase counterpart of i is not I, but İ... And in return, the I is not transformed to i, but a "dotless i": ı. Don't underestimate this, it can be a deadly mistake...

Why hexadecimal is not case sensitive in Java?

Because the Java Language Specification says it isn't case-sensitive.

Under 3.10.1. Integer Literals:

A hexadecimal numeral consists of the leading ASCII characters 0x or 0X followed by one or more ASCII hexadecimal digits interspersed with underscores, and can represent a positive, zero, or negative integer.

Hexadecimal digits with values 10 through 15 are represented by the ASCII letters a through f or A through F, respectively; each letter used as a hexadecimal digit may be uppercase or lowercase.

Case sensitive order for Strings

Case-sensitive ordering is the default; i.e. String#compareTo is case-sensitive. Therefore, there is no explicit Comparator for it.

Collections.sort(myStringList);  // case sensitive ("natural ordering")

Collections.sort(myStringList, String.CASE_INSENSITIVE_ORDER); // case insensitive


Related Topics



Leave a reply



Submit