Java compilation failure when using generics parameter in inner class - java

Please take a look at the code snippet below:
interface IFoo<E>{
void doFoo(E env);
}
class A<E>{
public void doA(E env){}
}
public class Foo<E> implements IFoo<E>{
public A<E> a;
#Override
public void doFoo(E env) {
a.doA(env);
}
private class FooInner<E> implements IFoo<E>{
#Override
public void doFoo(E env) {
a.doA(env);
}
}
}
Eclipse complains inside of private inner class a.doA(env) with the following message.
The method doA(E) in the type A<E> is not applicable for the arguments (E)
It doesn't seem like accessibility issue because non-static inner class have an access to all instance variables of the outter class. It looks like I defined my generics wrong somewhere. Can anyone explain me what I am doing wrong here?

You've used the same generic parameter name for the inner class, so the type E of the inner class is shadowing the E of the outer class.
Remove generic parameter from the inner class, like this:
public class Foo<E> implements IFoo<E>{
...
private class FooInner implements IFoo<E>{ // "E" here is the same "E" from Foo
#Override
public void doFoo(E env) {
a.doA(env);
}
}
}

The type of the enclosing class is part of the type of the inner class. FooInner is already parameterized by E, because it's part of the outer class; the explicit parameterization is redundant and incorrect, because it's actually trying to introduce a new type parameter using the same name as the existing one. Just remove the <E> in private class FooInner<E>, and you're golden.

Related

Java : generic type with type parameters?

I have a class like this :
public class MyClass <T extends Model1, X extends Model2> {
private CommonMessage<T,X> someMethod() {
....
}
}
Now I have a customized message type MyMessage extends CommonMessage, so I want to know how to have generic type that still having T and X as parameters ? For example :
public class MyClass <M extends CommonMessage, T extends Model1, X extends Model2> {
private M<T,X> someMethod() {
....
}
}
Short answer:
First of all as CommonMessage is generic, extending it in a non-generic way is very bad so you should have done M extends CommonMessage<T, X> And this way because type parameter passed to CommonMessage at class declaration you should not mention this parameter type again at method return type so method return type should be M.
Long answer:
I know you do know this definitions but sometimes we as human forget simple things. First we should consider what generics are created for, with generics we can create classes with different parameter types, this parameter types will be provided when they are extended by another class or when we create new instance of them with new() operator, so when we are writing our class we don't know the exact type for those parameter and we want to delay this decision until later, it is contradictory to something you are doing in your class because here your method is private and you can't change its implementation in your child class(the class which inherited from your class). But know we can change your implementation to something like this which will be compiled well:
public class MyClass<M extends CommonMessage<T, X>, T extends Model1, X extends Model2> {
private M method1(){
...
}
}
public class CommonMessage<T, X>{
}
public class MyMessage<T, X> extends CommonMessage<T, X>{
}
public class Model1{
}
public class Model2{
}
although this implementation will be compiled the problem is that when you are writing your private method(method1) you don't know what is the type of M at the time of writing this class because it will be passed when we want to create new instance of this class or when we inherit another class from this class. so what type of Object do you want to create and return in your method1? the only thing that you know here is that its type is M which extends CommonMessage but you don't know what the exact type of M is at the time of writing your private method(method1)!
And on the top of that you can't delegate this decision to your subclass(because this method is private). Now the question is that why it is allowed and compiled well when we don't know the exact type of M? for a moment forget this question I will make it clear after explaining correct approach. so what is the correct approach? Think about it, the person who write subclass does know exactly what the type of parameter M is and they can create appropriate instance of M in implementation of method1 to return from this method. so why not delegate this decision to subclass and making this method abstract? This completely make senses. in a nutshell we have some implementation like this:
public abstract class MyClass<M extends CommonMessage<T, X>, T extends Model1, X extends Model2> {
public abstract M method1();
}
public class CommonMessage<T, X>{
}
public class MyMessage<T, X> extends CommonMessage<T, X>{
}
public class Model1{
}
public class Model2{
}
now lets get back to our question why first program that I suggested to you compiled well? why we are allowed to have private method that its return type is generic that will be passed at instanciation or inheritance time?
because there are a lot of situations that make it correct and appropriate.
one situation is that our private method call another public method which return the appropriate type, like this:
public abstract class MyClass<M extends CommonMessage<T, X>, T extends Model1, X extends Model2> {
private M method1(){
return method2();
}
abstract M method2();
}
public class CommonMessage<T, X>{
}
public class MyMessage<T, X> extends CommonMessage<T, X>{
}
public class Model1{
}
public class Model2{
}

Cast Argument for abstract method with Type parameter

I don't know if its completely possible to do this, but here it goes.
I have an abstract class. Lets call it class 'A'. It looks like this:
public abstract class A <E, T>
It also has the following abstract method.
public abstract Object getEntityId(E entity);
So I can create more classes extending the A class as long as I implement the abstract getEntityId method. For example a class called 'ExtendedA'.
But also I have a secondary class, called it B. It's not abstract and goes like this :
public class B<T>
(notice the type parameter)
B has a field of type A, which should be an extended class of A (such a ExtendedA). It also contains a List of T such as this:
private A<?,?> myA;
private List<T> myList;
At some point, I need to invoke the abstract getEntityId method in class B for every element in myList, but I can't quite get the cast correctly. I feel like I'm missing something really basic.
for (T t : myList) {
if (myA.getEntityId(t)!=null) {//does not compile and I can't grasp how should I cast it.
}
}
Thanks in advance.
If your B class looks like this:
public class B<T> {
private A<?,?> myA;
void someMethod() {
for (T t : myList) {
if (myA.getEntityId(t)!=null) {
}
}
}
}
Then sure, it won't compile: the parameter of getEntityId is ?, and you're trying to pass it a T. ? doesn't mean "any type", it means "a specific type, just one that I don't know".
To pass a T to getEntityId(), the first type parameter of A needs to be T:
private A<T,?> myA;
In order for the code to work, Make it a complete getter method than trying to set value in runtime as it is completely illegal to do it on a wildcard. Either pass the reference private A myA or private A<(some known reference),?> myA or remove the parameter from myA.getEntityId(t)
Also declare a anonymous class and implement the method before calling the method getEntityId()
public class B<T>{
private A<T,?> myA;
private List<T> myList;
public void anycall(){
for (T t : myList) {
if (myA.getEntityId(t)!=null) {
}
}
}
}

Instantiating anonymous inner classes in Java with additional interface implementation

Let's say I have the following two class/interface definitions:
public abstract class FooClass {
public abstract void doFoo();
}
and
public interface BarInterface {
public void doBar();
}
If I want to make an anonymous inner class that extends/implements both, do I need to do this:
public abstract class BothClass extends FooClass implements BarInterface {}
...
new BothClass() {
public void doFoo() {
System.out.println("Fooooooooo!!!!");
}
public void doBar() {
System.out.println("Baaaaaaaar!!!!");
}
}.doBar();
Or is there a short-cut that allows me to not define BothClass? Something like this, maybe:
new (FooClass implements BarInterface)() {
public void doFoo() {
System.out.println("Fooooooooo!!!!");
}
public void doBar() {
System.out.println("Baaaaaaaar!!!!");
}
}.doBar();
(This idea gives me several errors, none of which are helpful here)
Let's go to the JLS:
An anonymous class declaration is automatically derived from a class
instance creation expression by the Java compiler.
where a class instance creation expression is
ClassInstanceCreationExpression:
new TypeArgumentsopt TypeDeclSpecifier TypeArgumentsOrDiamondopt
( ArgumentListopt ) ClassBodyopt
Primary . new TypeArgumentsopt Identifier TypeArgumentsOrDiamondopt
( ArgumentListopt ) ClassBodyopt
TypeArgumentsOrDiamond:
TypeArguments
<>
ArgumentList:
Expression
ArgumentList , Expression
So, no, the Java language specification does not allow any shortcuts for making your anonymous class implement more interfaces than the type you're sub-typing.
So, to determine the type of the anonymous class
If the class instance creation expression ends in a class body, then
the class being instantiated is an anonymous class. Then:
If T denotes an interface, then an anonymous direct subclass of Object
that implements the interface named by T is declared.
[...]
Let T be the type named by the Identifier and any type arguments. An
anonymous direct subclass of the class named by T is declared. The
body of the subclass is the ClassBody given in the class instance
creation expression.
Your alternative is the way to do it.
You can also use local classes.
An anonymous class
FooClass f = new FooClass() {
public void doFoo() {}
};
is just a convenient shorthand for a local class definition with a generated name
class $anon extends FooClass {
public void doFoo() {}
}
FooClass f = new $anon();
If you want to implement interfaces just write the local class definition explicitly
class LocalFoo extends FooClass implements BarInterface {
// method declarations here
}
LocalFoo lf = new LocalFoo();

Overriding non-parameterized classes nested in a parameterized outer class in Java

Can someone please help with the syntax of subclassing a non-parameterized nested class inside a parameterized outer class, like the following?
public abstract class Foo<T> {
public class Bar {
Set<T> aSet;
}
abstract class Baz {
abstract void doSomething(Map<? extends Bar, T> aMap);
}
}
Then in a separate file, I'm not entirely sure how to define the type variable S here without parameterizing ConcreteBaz. And I can't use a wildcard variable like extends Foo<?>.Baz (I think) because I need access to that generic type variable in the doSomething method:
public class ConcreteBaz extends Foo<S>.Baz { // compilation error
public ConcreteBaz(Foo<S> foo) { foo.super(); }
public void doSomething(Map<? extends Foo<S>.Bar, S> aMap) { ... }
}
Can someone please help me figure out a way around this? Thanks.
Declare S as a type parameter:
public class ConcreteBaz<S> extends Foo<S>.Baz {
Otherwise the compiler will think S is a concrete type instead of a type parameter.
Complete example:
public class ConcreteBaz<S> extends Foo<S>.Baz {
public ConcreteBaz(Foo<S> foo) {
foo.super();
}
#Override
void doSomething(Map<? extends Foo<S>.Bar, S> aMap) {
// ...
}
}
Your problem is that the nested class is nonstatic. I'll check it out, but I'm pretty sure you cannot subclass such classes, except maybe if nested in the same class, or when creating an anonymous type.
Is declaring the nested class static viable? Them it would definitely work.
Edit: scratch all that. I don't have a compilation error. What is S in your case? You do realize you have to pass a concrete class to Foo, and cannot leave it parametrized with an unknown parameter S?
If ConcreteBaz needs to refer to the type parameter, that implies that it needs the type parameter itself:
public class ConcreteBaz<S> extends Foo<S>.Baz {

Java generic method inheritance and override rules

I have an abstract class that has a generic method and I want to override the generic method by substituting specific types for the generic parameter. So in pseudo-code I have the following:
public abstract class GetAndParse {
public SomeClass var;
public abstract <T extends AnotherClass> void getAndParse(T... args);
}
public class Implementor extends GetAndParse {
// some field declarations
// some method declarations
#Override
public <SpecificClass> void getAndParse(SpecificClass... args) {
// method body making use of args
}
}
But for some reason I'm not allowed to do this? Am I making some kind of syntax error or is this kind of inheritance and overriding not allowed? Specifically I'm getting an error about #Override because the eclipse IDE keeps reminding me to implement getAndParse.
Here's how I want the above code to work. Somewhere else in my code there is a method that expects instances of objects that implement GetAndParse which specifically means that they have a getAndParse method that I can use. When I call getAndParse on that instance the compiler checks to see whether I have used specific instances of T in the proper way, so in particular T should extend AnotherClass and it should be SpecificClass.
What we are having here is two different methods with individual type parameters each.
public abstract <T extends AnotherClass> void getAndParse(Args... args);
This is a method with a type parameter named T, and bounded by AnotherClass, meaning each subtype of AnotherClass is allowed as a type parameter.
public <SpecificClass> void getAndParse(Args... args)
This is a method with a type parameter named SpecificClass, bounded by Object (meaning each type is allowed as a type parameter). Do you really want this?
Is the type parameter used inside Args? I think the problem would be there.
The meaning of
public abstract <T extends AnotherClass> void getAndParse(T... args);
is that the caller of the method can decide with which type parameter he wants to call the method, as long as this is some subtype of AnotherClass. This means that in effect the method can be called with any objects of type AnotherClass.
Since the caller can decide the type parameter, you can't in a subclass narrow down the parameter type to SpecificClass - this would not be an implementation of the method, but another method with same name (overloading).
Maybe you want something like this:
public abstract class GetAndParse<T extends AnotherClass> {
public SomeClass var;
public abstract void getAndParse(T... args);
}
public class Implementor extends GetAndParse<SpecificClass> {
// some field declarations
// some method declarations
#Override
public void getAndParse(SpecificClass... args) {
// method body making use of args
}
}
Now the getAndParse method implements the parent class' method.
You are seeing this problem because of the concept called "Erasure" in Java Generics.
Java uses "erasure" to support backward compatibility. i.e Java code which did not use generics.
Erasure Procedure:
The compiler will first do a type checking and then it will remove(erase) all the type parameters as much as possible, and also insert TypeCasting where ever necessary.
example:
public abstract <T extends AnotherClass> void getAndParse(T paramAnotherClass);
will become
public abstract void getAndParse(AnotherClass paramAnotherClass);
In class "Implementor.java",
The code
public <SpecificClass> void getAndParse(T paramAnotherClass)
will become
public void getAndParse(SpecificClass paramAnotherClass){ }
the compiler will see that you have not implemented the abstract method correctly.
There is a type mismatch between the abstract method and the implemented method. This is why you are seeing the error.
More details can be found here.
http://today.java.net/pub/a/today/2003/12/02/explorations.html
You cannot override to specific type T because there is in fact (at the bytecode level if you wish) only one method getAndParse because of type erasure (see other answer):
public abstract void getAndParse(AnotherClass... args); // (1)
For every type of T, the same method is used.
You can overload it (I think):
public void getAndParse(SpecificClass... args); // (2)
but this will not a different method from (1) ant it will not be called by generic code:
T x = whatever;
object.getAndParse(x); // Calls (1) even if T is derived from SpecificClass
No, it's not valid. What would happen if someone with a GetAndParse reference called it with a different class extending AnotherClass?
That becomes a nonsense when someone has a reference to type GetAndParse and tries to call the getAndParse method. If Cat and Dog extend AnotherClass. I should expect to be able to call GetAndParse#getAndParse with either a Cat or a Dog. But the implementation has tried to restrict it and make it less compatible!
Static method can't override
class Vehicle{
static void park(int location){
System.out.println("Vehicle parking..");
}}
class Car extends Vehicle{
#Override //error
void park(int location) { //error
System.out.println("Car Parking..");
}}
Private method can't override
class Vehicle{
private void park(int location){
System.out.println("Vehicle parking..");
}
void callPark(){
park(100);
}}
class Car extends Vehicle{
//#Override
void park(int location) {
System.out.println("Car Parking..");
}}
class Demo {
public static void main(String[] args) {
Vehicle v1=new Car();
v1.callPark();
}}
Final method can't override
class Vehicle{
final void park(int location){
System.out.println("Vehicle parking..");
}}
class Car extends Vehicle{
//#Override
void park(int location) { //error
System.out.println("Car Parking..");
}}

Categories