1

I'm having an hirarchy like this:

class Foo {
...
}
class Bar extends Foo {
...
}
class Baz extends Foo {
...
}

And now I'm trying to declare an object like this in class foo:

Class<? extends Foo> anyName;

Then there is some method where I want to do this:

anyName = new Foo();

But it won't let me do that. Can anyone help me out?

I've already read several guides/tutorials/documents on generics and wildcards. But I haven't fount quite the solution to this problem.

EDIT: Fixed the capitalization. Sorry that was a typing error. My original classes are indeed like that.

EDIT2: The goal here is to get a singleton-instance of Foo.

EDIT3: I'm really sorry, NOW it should be correct! Shame on me :/

mortalis
  • 2,060
  • 24
  • 34
Hann3s
  • 19
  • 3
  • `Class` is not the reserved word to declare a new type. Use `class` instead. – riccardo.cardin May 24 '17 at 07:57
  • I'm sorry, I did not check if my capitalization is correct :/ now it should be more clear. – Hann3s May 24 '17 at 08:03
  • If you think `Class extends Foo>` represents an *instance* of `Foo` (or some subtype), you're mistaken. It represents the runtime *class* of some subtype of `Foo`. All you need in your example is the type `Foo` itself. – shmosel May 24 '17 at 08:24

3 Answers3

3

A Class<Foo> is not type compatible with a Foo.

Class<Foo> c = new Foo();

... won't work for that reason.

If you want an object of type Class, the normal way to do it is to use the class name followed by .class:

Class<Foo> c = Foo.class

You can make this handle subclasses like this:

Class<? extends Foo> c = Bar.class;

However, you probably wouldn't be asking this question if you knew classes well enough to have a reason to have a variable of that type. Normally we want an instance of Foo or Bar:

Foo a = new Foo();
Bar b = new Bar();
Foo c = new Bar(); // type compatible because of inheritance

You mention that you want to call a method and/or cast your variable.

You can do:

Foo a = ...;
if(a instanceof Bar) {
    Bar b = (Bar) a;
    b.someMethodOfBar();
}

However, both casting and instanceof are "code smells" -- not necessarily wrong, but evidence that something could be designed better.

It would be better if your method was declared in Foo, perhaps as an abstract method, and overriden in Bar and Baz.

 Foo a = ...;
 a.someMethod();   // if it's a Bar, this is Bar.someMethod()
                   // if it's a Baz, this is Baz.someMethod()

This is called polymorphism and is one of the most important concepts in OO programming.

slim
  • 40,215
  • 13
  • 94
  • 127
2

I am not sure about what you are trying to get from here, but my suggestion is too long for a comment.

What you want to achieve is to get a variable which is an instance of Foo so you can do this anyName = new Foo(). But you also would like to be able to do this anyName = new Bar(); or this anyName = new Baz();.

If I am right here, you don't need to use generics. Instead, you just have to define anyName as follows:

Foo anyName;

Update based on the comments

You can't get an instance of an object you don't know. I would used one of this approaches:

You can just cast your variable to the time you need to. For example:

((Bar) anyName).someBarMethod();

Alternatively, you can create a generic method for getting the type you need. This is useful when you need some flexibility when you cast:

public <T extends Foo> T getFoo(Class<T> type){
    return (T) anyName;
}
JCalcines
  • 1,236
  • 12
  • 25
  • This is what I had first, but then the next problem comes into play: I want to call an method on anyName, but then I need to cast anyName of either Bar or Baz. And I can't find a way around that. – Hann3s May 24 '17 at 08:22
  • 1
    @Hann3s Sounds like you have an [XY Problem](https://meta.stackexchange.com/a/66378/304954). If you need to call some common method, it should be defined in the common class. If it's not common, then you'll have to keep separate variables or cast to the correct type before calling the method. This is often indicative of a deeper design flaw, but it's hard to help without more context. – shmosel May 24 '17 at 08:44
0

You can use the reflection API to create a new instance of whatever Class<? extends Foo> anyName is by using anyName.getDeclaredConstructor().newInstance()

Here is a detailed example: https://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html

davioooh
  • 23,742
  • 39
  • 159
  • 250
Wesley
  • 855
  • 1
  • 9
  • 23
  • 1
    OP clearly doesn't understand classes or inheritance properly yet -- reflection is not something they need in their life yet. – slim May 24 '17 at 08:57