I need to know if Java has a constructor that can not do data type verification statically and what it does, if it does the verification dynamically or leaves the construction without verification during execution.
I need to know if Java has a constructor that can not do data type verification statically and what it does, if it does the verification dynamically or leaves the construction without verification during execution.
Type verification is done at compile time, then the bytecodes that are interpreted by the Java virtual machine (JVM) are generated. There is an instruction from the JVM that could approach the behavior you ask, which is invokedynamic
. In this blog there is a very detailed and extensive explanation.
The compiler, once it has validated the Java code, converts it to bytecode and removes the information it had about the data type of the objects ( type erasure ). At run time, there is not enough information to know what type an object was, so it is common for certain operations of casting to be done blindly and with a good chance of failing:
String[] strings = new String[10];
Object[] objects = strings;
objects[0] = new Object(); //<-- java.lang.ArrayStoreException
I think this answers the last question: data types can not be verified dynamically at runtime. As for if there is a constructor whose type can not be verified at compile time, I suppose you mean some generic type. Java does not have inference of types like other languages, so everything has to have its type defined at compile time, even the lambda expressions in java8 that give the impression of not using types.
Another thing to consider would be the type security ( type safety ). Although the compiler validates types, it is very possible that it does not have all the information to ensure that the type of an operation is correct. From the implementations themselves this security must be reinforced by preventing external operations . For example, the class BigDecimal
does not allow operations that give results that can not be represented by itself:
BigDecimal a = new BigDecimal(3);
BigDecimal b = BigDecimal.ONE.divide(a); // <- java.lang.ArithmeticException
Ideally, the compiler should have the necessary information to validate the type resulting from these calculations. This is what Scala is trying to do with its new compiler, dotty , which can do complex types checks from a language type definition called DOT ( Dependent Object Types ).
Edited : from the comment of @ Luiggi-Mendoza, I'm going to put a similar code, but specific to type-erasure , without using arrays :
Vector<String> strings = new Vector<String>(10);
Vector objects = strings;
objects.add(new Object());
Object anObject = strings.get(0);
String aString = strings.get(0);
This code "compiles" , giving runtime error on the last line. Explained line by line:
Creating a Strings
vector:
Vector<String> strings = new Vector<String>(10);
casting a generic vector:
Vector objects = strings;
Since objects
is a generic vector, it does not fail to add an object:
objects.add(new Object());
When extracting an element from the vector, no conversion error occurs because the compiler has removed all implicit conversion to String
for efficiency:
Object anObject = strings.get(0);
On the other hand, if we want to convert it to String
it will give an error because it has lost information of the initial generic type that had the Vector<String>
:
String aString = strings.get(0); // <-- java.lang.ClassCastException:
// java.lang.Object cannot be cast to java.lang.String