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 classjava.net.PlainSocketImpl
, where that parameter is used, delegates onBoolean.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
How to Determine the Primitive Type of a Primitive Variable
Java.Rmi.Connectexception: Connection Refused to Host: 127.0.1.1;
Apache Spark - Foreach VS Foreachpartition When to Use What
How to Use Bufferedreader in Java
Checked VS Unchecked Exceptions in Java
Convert Xml to Java Object Using Jaxb (Unmarshal)
Suppress Deprecated Import Warning in Java
How to Use a Variable of One Method in Another Method
Is There Possibility of Sum of Arraylist Without Looping
How to Use Google's Gson API to Deserialize JSON Properly
Rejectedexecutionexception Inside Single Executor Service
JPA Query.Getresultlist() - Use in a Generic Way
Eclipse Autocomplete (Content Assist) with Facelets (Jsf) and Xhtml
Any Simple Way to Explain Why I Cannot Do List<Animal> Animals = New Arraylist<Dog>()
How to Set Eclipse Console Locale/Language