What protection does casting do? - java

The cast to Bar is necessary in this code. I'm trying to understand what problem it avoids. If the compiler would let me use the Foo as a Bar without casting, would it not be able to use the extended functionality that Bar could have? Or is there some more important reason? Or is the example too trivial to explain why I must cast?
class Foo { }
class Bar extends Foo { }
public class Main {
public static void main(String[] args) {
Foo f1 = new Bar();
Bar b1 = (Bar) f1;
}
}
Can we write a simple example where I see and understand that if I don't cast there will be trouble? I could think that the runtime could help itself without casting in the code above, but certainly I have not understood the deep details why I must do the casting.

This protects you from wrong casting. If you will want to use not casted class, which actually is now of type Bar what you will expect to see when using its method? For example you actually make f1 of type Foo, and then you try to make b1 of type Bar point to class Foo. You are trying to invoke method from Bar, but there is no implementation of it. What you expect? Compiler won't know either. In this case if you are trying to cast wrong class you will obtain just java.lang.ClassCastException, which we know how to protect from.

The necessity of the cast becomes more clear if you add another class to your hierarchy. Consider this set of classes instead:
class Foo {}
class Bar extends Foo {}
class Baz extends Foo {}
Now if you have a reference of type Foo, it may refer to a Foo instance, a Bar instance, or a Baz instance. Consider this code snippit:
Foo f;
if (Math.random() > 0.5) {
f = new Bar();
} else {
f = new Baz();
}
You can't simply call f a Bar, because it may be the case that f isn't a Bar, but rather a Baz. Hence, the cast is essentially saying , "I know there's a chance this may fail, but I have reason to believe it won't so go ahead and try it". For example, we could do the following:
Foo f;
if (Math.random() > 0.5) {
f = new Bar();
} else {
f = new Baz();
}
if (f instanceof Bar) {
Bar b = (Bar) f;
// do stuff with b...
}
Within the if block, we have reason to believe that f is a Bar instance, even though the java compiler can't be sure of that. (In this example it seems trivial, but there could be thousands of lines and multiple stack frames separating the if condition and the cast). Hence, we can make the cast with confidence.
If, however, you're wrong about that, that the cast is in fact not valid, you'll get a ClassCastException on the line where the cast was attempted. This makes the issue more clear: instead of getting the exception on a random line where the instance in question doesn't have the desired functionality, it happens where the conversion was attempted.

Related

Parameterize a class with one of a fixed set of types

Say I have a generic class Foo which can hold an object of type T. Furthermore, let's say I only want to be able to instantiate the class with objects that are one of two types. Finally, let's say that the lowest common upper bound of these two types is a type that has many more subclasses than those two types that I want to allow, so I can't simply specify an upper bound for the type parameter (as in class Foo<T extends Something>), because then I would allow to instantiate the class with other types than the two I expect.
For illustration, let's say I want Foo to hold only either a String or an Integer. The lowest common upper bound is Object, so specifying an upper bound won't do the trick.
Certainly, I could do something along the lines of
class Foo<T> {
private T obj;
public Foo(T obj) throws IllegalArgumentException {
if (!(obj instanceof String || obj instanceof Integer)) {
throw new IllegalArgumentException("...");
}
this.obj = obj;
}
}
However, in this case, I can still call the constructor with any object; if I try to instantiate it with something that is neither a String nor an Integer, I will get an exception at runtime.
I would like to do better. I would like the compiler to infer statically (i.e., at compile time) that I can only instantiate this class with objects that are either String or Integer.
I was thinking something along those lines might do the trick:
class Foo<T> {
private T obj;
public Foo(String s) {
this((T) s);
}
public Foo(Integer i) {
this((T) i);
}
private Foo(T obj) {
this.obj = obj;
}
}
This works, but it looks really, really odd. The compiler warns (understandably) about unchecked casts. Of course I could suppress those warnings, but I feel this is not the way to go. In addition, it looks like the compiler can't actually infer the type T. I was surprised to find that, with the latter definition of class Foo, I could do this, for instance:
Foo<Character> foo = new Foo<>("hello");
Of course, the type parameter should be String here, not Character. But the compiler lets me get away with the above assignment.
Is there a way to achieve what I want, and if yes, how?
Side question: why does the compiler let me get away with the assignment to an object of type Foo<Character> above without even so much as a warning (when using the latter definition of class Foo)? :)
Try using static factory method to prevent compiler warning.
class Foo<T> {
private T obj;
public static Foo<String> of(String s) {
return new Foo<>(s);
}
public static Foo<Integer> of(Integer i) {
return new Foo<>(i);
}
private Foo(T obj) {
this.obj = obj;
}
}
Now you create instance using:
Foo<String> foos = Foo.of("hello");
Foo<Integer> fooi = Foo.of(42);
Foo<Character> fooc = Foo.of('a'); // Compile error
However the following are still valid since you can declare a Foo of any type T, but not instantiate it:
Foo<Character> fooc2;
Foo<Character> fooc3 = null;
Foo<Object> fooob1;
Foo<Object> fooob2 = null;
one word: interface. You want your Z to wrap either A or B. Create an interface implementing the smallest common denominator of A and B. Make your A and B implement that interface. There's no other sound way to do that, AFAIK. What you already did with your constructors etc. is the only other possibility, but it comes with the caveats you already noticed (having to use either unchecked casts, or static factory wrappers or other code smells).
note: If you can't directly modify A and/or B, create wrapper classes WA and WBfor them beforehand.
example:
interface Wrapper {
/* either a marker interface, or a real one - define common methods here */
}
class WInt implements Wrapper {
private int value;
public WInt( int value ) { this.value = value; }
}
class WString implements Wrapper {
private String value;
public WString( String value ) { this.value = value; }
}
class Foo<T> {
private Wrapper w;
public Foo(Wrapper w) { this.w = w; }
}
because you call your private Foo(T obj) due to diamond type inference. As such, it's equal to calling Foo<Character> foo = new Foo<Character>("hello");
Long story short: You are trying to create a union of two classes in java generics which is not possible but there are some workarounds.
See this post
Well the compiler uses the Character class in T parameter. Then the String constructor is used where String is casted to T (Character in this case).
Trying to use the private field obj as a Character will most likely result in an error as the saved value is an instance of the final class String.
Generics is not suitable here.
Generics are used when any class can be used as the type. If you only allow Integer and String, you should not use generics. Create two classes FooInteger and FooString instead.
The implementations should be pretty different anyway. Since Integers and Strings are very different things and you would probably handle them differently. "But I am handling them the same way!" you said. Well then what's wrong with Foo<Double> or Foo<Bar>. If you can handle Integer and String with the same implementation, you probably can handle Bar and Double and anything else the same way as well.
Regarding your second question, the compiler will see that you want to create a Foo<Character>, so it tries to find a suitable overload. And it finds the Foo(T) overload to call, so the statement is perfectly fine as far as the compiler is concerned.

Why does a lambda need to capture the enclosing instance when referencing a final String field?

This is based on this question. Consider this example where a method returns a Consumer based on a lambda expression:
public class TestClass {
public static void main(String[] args) {
MyClass m = new MyClass();
Consumer<String> fn = m.getConsumer();
System.out.println("Just to put a breakpoint");
}
}
class MyClass {
final String foo = "foo";
public Consumer<String> getConsumer() {
return bar -> System.out.println(bar + foo);
}
}
As we know, it's not a good practice to reference a current state inside a lambda when doing functional programming, one reason is that the lambda would capture the enclosing instance, which will not be garbage collected until the lambda itself is out of scope.
However, in this specific scenario related to final strings, it seems the compiler could have just enclosed the constant (final) string foo (from the constant pool) in the returned lambda, instead of enclosing the whole MyClass instance as shown below while debugging (placing the breaking at the System.out.println). Does it have to do with the way lambdas are compiled to a special invokedynamic bytecode?
In your code, bar + foo is really shorthand for bar + this.foo; we're just so used to the shorthand that we forget we are implicitly fetching an instance member. So your lambda is capturing this, not this.foo.
If your question is "could this feature have been implemented differently", the answer is "probably yes"; we could have made the specification/implementation of lambda capture arbitrarily more complicated in the aim of providing incrementally better performance for a variety of special cases, including this one.
Changing the specification so that we captured this.foo instead of this wouldn't change much in the way of performance; it would still be a capturing lambda, which is a much bigger cost consideration than the extra field dereference. So I don't see this as providing a real performance boost.
If the lambda was capturing foo instead of this, you could in some cases get a different result. Consider the following example:
public class TestClass {
public static void main(String[] args) {
MyClass m = new MyClass();
m.consumer.accept("bar2");
}
}
class MyClass {
final String foo;
final Consumer<String> consumer;
public MyClass() {
consumer = getConsumer();
// first call to illustrate the value that would have been captured
consumer.accept("bar1");
foo = "foo";
}
public Consumer<String> getConsumer() {
return bar -> System.out.println(bar + foo);
}
}
Output:
bar1null
bar2foo
If foo was captured by the lambda, it would be captured as null and the second call would print bar2null. However since the MyClass instance is captured, it prints the correct value.
Of course this is ugly code and a bit contrived, but in more complex, real-life code, such an issue could somewhat easily occur.
Note that the only true ugly thing, is that we are forcing a read of the to-be-assigned foo in the constructor, through the consumer. Building the consumer itself is not expected to read foo at that time, so it is still legit to build it before assigning foo – as long as you don't use it immediately.
However the compiler will not let you initialize the same consumer in the constructor before assigning foo – probably for the best :-)
You are right, it technically could do so, because the field in question is final, but it doesn't.
However, if it is a problem that the returned lambda retains the reference to the MyClass instance, then you can easily fix it yourself:
public Consumer<String> getConsumer() {
String f = this.foo;
return bar -> System.out.println(bar + f);
}
Note, that if the field hadn't been final, then your original code would use the actual value at the time the lambda is executed, while the code listed here would use the value as of the time the getConsumer() method is executed.
Note that for any ordinary Java access to a variable being a compile-time constant, the constant value takes place, so, unlike some people claimed, it is immune to initialization order issues.
We can demonstrate this by the following example:
abstract class Base {
Base() {
// bad coding style don't do this in real code
printValues();
}
void printValues() {
System.out.println("var1 read: "+getVar1());
System.out.println("var2 read: "+getVar2());
System.out.println("var1 via lambda: "+supplier1().get());
System.out.println("var2 via lambda: "+supplier2().get());
}
abstract String getVar1();
abstract String getVar2();
abstract Supplier<String> supplier1();
abstract Supplier<String> supplier2();
}
public class ConstantInitialization extends Base {
final String realConstant = "a constant";
final String justFinalVar; { justFinalVar = "a final value"; }
ConstantInitialization() {
System.out.println("after initialization:");
printValues();
}
#Override String getVar1() {
return realConstant;
}
#Override String getVar2() {
return justFinalVar;
}
#Override Supplier<String> supplier1() {
return () -> realConstant;
}
#Override Supplier<String> supplier2() {
return () -> justFinalVar;
}
public static void main(String[] args) {
new ConstantInitialization();
}
}
It prints:
var1 read: a constant
var2 read: null
var1 via lambda: a constant
var2 via lambda: null
after initialization:
var1 read: a constant
var2 read: a final value
var1 via lambda: a constant
var2 via lambda: a final value
So, as you can see, the fact that the write to the realConstant field did not happen yet when the super constructor is executed, no uninitialized value is seen for the true compile-time constant, even when accessing it via lambda expression. Technically, because the field isn’t actually read.
Also, nasty Reflection hacks have no effect on ordinary Java access to compile-time constants, for the same reason. The only way to read such a modified value back, is via Reflection:
public class TestCapture {
static class MyClass {
final String foo = "foo";
private Consumer<String> getFn() {
//final String localFoo = foo;
return bar -> System.out.println("lambda: " + bar + foo);
}
}
public static void main(String[] args) throws ReflectiveOperationException {
final MyClass obj = new MyClass();
Consumer<String> fn = obj.getFn();
// change the final field obj.foo
Field foo=obj.getClass().getDeclaredFields()[0];
foo.setAccessible(true);
foo.set(obj, "bar");
// prove that our lambda expression doesn't read the modified foo
fn.accept("");
// show that it captured obj
Field capturedThis=fn.getClass().getDeclaredFields()[0];
capturedThis.setAccessible(true);
System.out.println("captured obj: "+(obj==capturedThis.get(fn)));
// and obj.foo contains "bar" when actually read
System.out.println("via Reflection: "+foo.get(capturedThis.get(fn)));
// but no ordinary Java access will actually read it
System.out.println("ordinary field access: "+obj.foo);
}
}
It prints:
lambda: foo
captured obj: true
via Reflection: bar
ordinary field access: foo
which shows us two things,
Reflection also has no effect on compile-time constants
The surrounding object has been captured, despite it won’t be used
I’d be happy to find an explanation like, “any access to an instance field requires the lambda expression to capture the instance of that field (even if the field is not actually read)”, but unfortunately I couldn’t find any statement regarding capturing of values or this in the current Java Language Specification, which is a bit frightening:
We got used to the fact that not accessing instance fields in a lambda expression will create an instance which doesn’t have a reference to this, but even that isn’t actually guaranteed by the current specification. It’s important that this omission gets fixed soon…

Java code snippet output explanation required

My code is:
class Foo {
public int a=3;
public void addFive() {
a+=5;
System.out.print("f ");
}
}
class Bar extends Foo {
public int a=8;
public void addFive() {
this.a += 5;
System.out.print("b ");
}
}
public class TestClass {
public static void main(String[]args) {
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
}
}
Output:
b 3
Please explain to me, why is the output for this question "b 3" and not "b 13" since the method has been overridden?
F is a reference of type Foo, and variables aren't polymorphic so f.a refers to the variable from Foo which is 3
How to verify it?
To test this you can remove a variable from Foo , it will give you compile time error
Note: Make member variable private and use accessors to access them
Also See
Why use getters and setters?
You cannot override variables in Java, hence you actually have two a variables - one in Foo and one in Bar. On the other hand addFive() method is polymorphic, thus it modifies Bar.a (Bar.addFive() is called, despite static type of f being Foo).
But in the end you access f.a and this reference is resolved during compilation using known type of f, which is Foo. And therefore Foo.a was never touched.
BTW non-final variables in Java should never be public.
With such a question, the SCJP exam is assessing your knowledge of what is known as hiding. The examiner deliberately complicated things to try to make you believe that the behavior of the program depends only on polymorphism, wich it doesn't.
Let's try to make things a bit clearer as we remove the addFive() method.
class Foo {
public int a = 3;
}
class Bar extends Foo {
public int a = 8;
}
public class TestClass {
public static void main(String[]args) {
Foo f = new Bar();
System.out.println(f.a);
}
}
Now things are a bit less confusing. The main method declares a variable of type Foo, which is assigned an object of type Bar at runtime. This is possible since Bar inherits from Foo.The program then refers to the public field a of the variable of type Foo.
The error here would be to believe that the same kind of concept known as overriding applies to class fields. But there is no such a concept for fields: the public field a of class Bar is not overriding the public field a of class Foo but it does what is called hiding. As the name implies, it means that in the scope of the class Bar, a will refer to Bar's own field which has nothing to do with Foo's one. (JLS 8.4.8 - Inheritance, Overriding, and Hiding)
So, when we are writing f.a, which a are we referring to? Recall that resolution of the field a is done at compile time using the declaring type of the object f, which is Foo. As a consequence, the program prints '3'.
Now, lets add an addFive() method in class Foo and override it in class Bar as in the exam question. Here polymorphism applies, therefore the call f.addFive() is resolved using not the compile time but the runtime type of object f, which is Bar, and thus is printed 'b '.
But there is still something we must understand: why the field a, which was incremented by 5 units, still sticks to the value '3'? Here hiding is playing around. Because this is the method of class Bar which is called, and because in class Bar, every a refers to Bar's public field a, this is actually the Bar field which is incremented.
1) Now, one subsidiary question: how could we access the Bar's public field a from the main method? We can do that with something like:
System.out.println( ((Bar)f).a );
which force the compiler to resolve the field member a of f as Bar's a field.
This would print 'b 13' in our example.
2) Yet another question: how could we work around hiding in addFive() method of class Bar to refer not to the Bar's a field but to its superclass eponimous field ? Just adding the super keyword in front of the field reference does the trick:
public void addFive() {
super.a += 5;
System.out.print("b ");
}
This would print 'b 8' in our example.
Note that the initial statement
public void addFive() {
this.a += 5;
System.out.print("b ");
}
could be refined to
public void addFive() {
a += 5;
System.out.print("b ");
}
because when the compiler is resolving the field a, it will start to look in the closest enclosing scope from within the method addFive(), and find the Bar class instance, eliminating the need to use explicitely this.
But, well, this was probably a clue for the examinee to solve this exam question !
Since you are doing f.a you will get the value of a from the class Foo. if you had called a method to get the value, e.g getA() then you would have gotten the value from the class Bar.

Why do raw types in one place cause generic callsites somewhere else to be treated as raw?

Consider this example:
import java.util.*;
class Foo<T> {
public int baz(List<String> stringlist) { return 1; }
public int baz(ArrayList<Object> objectlist) { return 2; }
public static void main(String[] args) {
Foo<String> foo = new Foo<String>(); // (A)
//Foo foo = new Foo(); // (B)
System.out.println(foo.baz(new ArrayList<String>()));
}
}
Why does it print 1 in (A), but 2 with (B)?
I know how method resolution works, so no need to explain that to me.
I want to know the deeper motivation behind this "feature".
Why is there no erasure warning about it? (There is just one about Foo foo = new Foo().)
Why does method resolution use erased semantics although the generic type is given?
It's because when the compiler is resolving overloads, it considers each method as either generic or non-generic, never a mixture of the two, so the candidates are:
Foo<T>.baz(List<String>)
Foo<T>.baz(ArrayList<Object>)
if foo is a Foo<String>, or
Foo.baz(List)
Foo.baz(ArrayList)
if foo is a Foo.
There is no such thing as Foo.baz(List<String>). Either all type parameters are considered or none are. (I am not aware of this being explicitly stated in the JLS, but it makes sense since treating a generic method as if it were the raw equivalent is a backwards-compatibility feature.)
In the first case, Foo<T>.baz(List<String>) matches but Foo<T>.baz(ArrayList<Object>) does not.
In the second case both functions match, and Foo.baz(ArrayList) is more specific, so it is chosen.
It won't even compile case (A) if you only keep the single method baz(ArrayList<Object>) (error: method cannot be applied to given type).
I guess ArrayList<String> is not a subclass of ArrayList<Object>.
It's weird that it does compile in case (B), but they must have taken some weird decisions to kept backward compatibility with non-generic collections.

C++'s out parameter object creation and JNA

Disclaimer: I ignore pretty much everything about C++, so I hope I'm not saying stupid things here, if I am, please feel free to correct me.
As a Java developer, when I want to create a new object, I use a constructor method that will allocate this object in memory and return a handle on it for me, and I will store this handle in a variable, I do it like this.
Foo o = new Foo();
But in C++, I've been given to understand, that despite the fact it is possible to do so
Foo createFoo(){
Foo f;
f.doSomething();
return f;
}
// ...
Foo f = createFoo();
I can also define a handle by myself, and then call a initializer on it that will allocate memory and bind the handle on it, like this:
void initializeFoo(Foo **f){
f.doSomething();
return;
}
// ...
Foo f;
initializeFoo(&f);
So my question is, what happens when we want to use those C++ methods in Java, with JNA?
Let's suppose I have the following C++ header:
typedef struct Foo f;
Foo createFoo();
void initializeFoo(Foo **f);
As I don't have any idea on what a Foo is, or what the Foo structure contains, I'm just going to create a JNA PointerType to declare my structure:
public class Foo extends PointerType{
public Foo(Pointer address) {
super(address);
}
public Foo() {
super();
}
}
Using the createFoo method should be pretty easy as well:
public class TestFoo{
static{
System.loadLibrary("foolib");
}
public static void main(String[] args){
FooLib lib = (FooLib)Native.loadLibrary("foolib", FooLib.class);
Foo f = lib.createFoo();
}
Right?
But my question is, how can I use the initializeFoo function??? I suppose I would have to create a Pointer and give it to the function, but how do I create a non NULL pointer in JNA? I tried the following code, but it results in an EXCEPTION_ACCESS_VIOLATION.
public class TestFoo{
static{
System.loadLibrary("foolib");
}
public static void main(String[] args){
FooLib lib = (FooLib)Native.loadLibrary("foolib", FooLib.class);
Foo f = new Foo();
lib.initializeFoo(f); // EXCEPTION_ACCESS_VIOLATION
lib.initializeFoo(f.getPointer()); // EXCEPTION_ACCESS_VIOLATION
}
Any idea?
Thanks!
Foo f;
initializeFoo(&f);
initializeFoo() does not "allocate memory and bind the handle" for f, as you say. Foo f; creates f and allocates it in memory. initializeFoo() could do something like assign values to f's member properties, and the like, as well as create another Foo object and assign it to f, but it does not do what you say.
On the other hand,
Foo *f;
f = new Foo();
declares a Foo pointer. new allocates memory and creates a Foo object, and assigns the memory location to f (you can think of a pointer as a integer containing an address).
I think you want to learn more about C++ and pointers before you go any further.
As I don't have any idea on what a Foo is, or what the Foo structure contains, I'm just going to create a JNA PointerType to declare my structure
This makes it impossible to allocate memory for Foo, as you have to know how much memory you need to allocate. For c structures jna needs a java class mirroring the structure or if you at least know its size you can try to use the Memory class which has a ctor taking a size argument.
For c++ structures and classes using c++ features like inheritance this fails since the required memory and layout depends on the compiler and enabled optimisations.

Categories