I have a parameterized class. I would like to get the name of the class represented by the class name. For instance, what I want to do is this:
public T foo(){
System.out.println(T.class.getName());
}
You can't do it this way, since T isn't known at compile time. You could achieve something similar like so:
public void foo(T t) {
System.out.println(t.getClass().getName());
}
Note that this takes an instance of T and would print out the name of its dynamic type.
Whether or not this is a good enough substitute depends on your use case.
Java generics don't work that way. If you have any bounds on T, you can access the bounds by querying the type variable definition. E.g.:
public class Foo<T extends Bar>{}
will let you get at Bar, but not at the subtype of Bar you are actually using. It doesn't work, sorry.
Read the Java Generics FAQ for more info.
BTW: One common solution to this problem is to pass the subtype of T into your class, e.g.
public T foo(Class<? extends T> tType){
System.out.println(tType.getName());
}
I know it's cumbersome, but it's all Java generics allow.
public T foo(T t){
System.out.println(t.getClass().getName());
}
Related
I have
1) a basic interface,
2) a few classes that implement this interface,
3) and a generic class that I want to accept, as a parameter, any of the implementing classes
I have tried the following:
public class Foo extends Bar<? extends SomeInterface> {
public Foo(List<? extends SomeInterface> someInterfaceList) {
super(someInterfaceList);
}
...
}
I receive the error No Wildcard Expected. Elsewhere in my code I have statements such as List<? extends SomeInterface> and I receive no errors, so why am I running into problems here? How can I fix this problem and still get the desired results?
I have tried search 'No Wildcard Expected' and 'wildcard in class declaration' to no avail. Thanks in advance!
It sounds like you want to declare a generic type argument that you will reference elsewhere. Wildcards only make sense when the type is used only once, and when declaring a generic type parameter for a class this doesn't make any sense.
Try this instead:
public class Foo<T extends SomeInterface> extends Bar<T> {
public Foo(List<T> someInterfaceList) {
super(someInterfaceList);
}
...
}
As your code was written, there was no way for the user of your class to specify the generic type argument for Bar<>, since Foo wasn't itself a generic type.
Further, if this were possible, it would have been possible for the generic argument to Bar<> to be different than the generic argument to List<> -- as long as both types implemented SomeInterface there would not be a compile-time issue with these definitions, but there could have been a much more confusing error message later when you incorrectly assumed that both types must be the same.
So, declare the generic type once as a generic argument to the Foo class, and then use that type (T in my example) elsewhere to refer to that type instead of accepting some new generic type argument that may not refer to the same type.
I'm not exactly sure what you're looking for, so it might help if you could provide a little more detail. Perhaps you could be a little more specific about how you're planning to instantiate and use these objects?
Anyways, I think you might be looking for something like this:
import java.util.List;
public class Foo<T extends SomeInterface> {
public Foo(List<T> someInterfaceList) {
for (T item : someInterfaceList) {
// do something with each item
}
}
}
class Bar<T> {}
interface SomeInterface<T> {
T x(T y);
}
Or, alternatively, you could just use the following for the constructor:
public Foo(List someInterfaceList) {
but you wouldn't have an easy way of getting the type T of the items in the list.
I'd like to do something like this:
private Class<? extends Enum<?> implements IMultiBlockEnum> typeEnum;
How would I do that? The "&" instead of "implements" doesn't work, but Eclipse doesn't give a proper explanation either.
Christopher Klinge
You can only use & when declaring an inferred parameter type, like this:
<T extends Enum & IMultiBlockEnum> void x(T a) {}
Wildcard types may not specify a type intersection as an upper bound.
If you start wondering why it is so, consider what would be the return type of typeEnum.newInstance(). It would have to be both Enum<?> and IMultiBlockEnum at the same time.
For the relevant JLS quote please refer to this answer.
P.S. Another thing that makes little sense in your example is that you end up using two independent wildcards, but obviously want it to be captured as the same type.
You can't extend Enum
Enum types are final by design.
You can create your own class using the original Enum as you like without extend it
If you want to require that the implementation be a certain enum, but also implement an interface, you need to define your own enum "class" implementing the interface(s) , e.g.
public enum MyFancyEnum implements IMultiBlockEnum {
A,B,C,D;
// put code to implement IMultiBlockEnum here, e.g.
public void doTheMultiBlockEnumStuff(String input) {
...
}
}
and then declare your variable as a MyFancyEnum, e.g.
private MyFancyEnum typeEnum = MyFancyEnum.C;
I have recently started reading Core Java. But I am having a hard time grasping the concept of wildcards.
Specifically, I'm confused about the difference between the following:
public class A<T extends {some_class}> {/*...*/}
and
public class A<? extends {some_class}> {/*...*/}
Can anyone help me understand the difference if there is at all?
The difference is that you cannot use the ? elsewhere while you can use T. For example:
public class Foo<T extends Number> {
T value; // you can declare fields of type T here
int foo() {
// Since you said T extends Number, you can call methods of Number on value
return value.intValue();
}
}
So why would you use ? at all? If you don't need the type. It wouldn't make sense to use it in a class definition any way that I can think of. But you could use it in a method like this:
int getListSize(List<?> list) {
return list.size();
}
Any kind of method where you're more interested in the overall class and it has a method that doesn't involve the paramaterized type would work here. Class.getName() is another example.
They are the same, except with the wildcard you can't refer to the type in the code of your class. Using T names the type.
In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific). The wildcard is never used as a type argument for a generic method invocation, a generic class instance creation, or a supertype.
The Type T is a defined type or known type
Hope this helps
? extends some class or T extends some_class
means some_class itself or any of its children and anything that would work with instanceof some_class.
As per conventions T is meant to be a Type and ? is unknown type.
Is it possible to accept only supertypes of the generic Type of a class?
What I'm looking for is something like:
class <T extends Object> MyClass {
public <TS super T> void myMethod(TS someObjectSuperToTheClass) {
//do stuff
}
}
I don't really need it anymore (and it's probably not all that useful to begin with) but I'm curious if this is at all possible and if not, why.
Think about what it would mean in this case.
You want to assert that TS is either T, or any of its superclasses. But since TS is merely a reference, the actual someObjectSuperToTheClass parameter can be TS or a subclass.
Putting both halves together, in comes out that your code is entirely equivalent to
public void myMethod(Object someObjectSuperToTheClass) { //do stuff }
since together, you've got that TS can walk as high as it wants up the class hierarchy, and the parameter can walk down as far as it wants.
What was it you were trying to constrain the parameter to, with this syntax?
No you cannot! Only wildcards can have a super bound.
I'd like to define a generic type, whose actual type parameter can only be
One of the numeric primitive wrapper classes (Long, Integer, Float, Double)
String
I can meet the first requirement with a definition like this
public final class MyClass<T extends Number> {
// Implementation omitted
}
But I can't figure out how to meet both of them. I suspect this is not actually possible, because AFAIK there's no way to specify "or" semantics when defining a formal type parameter, though you can specify "and" semantics using a definition such as
public final class MyClass<T extends Runnable & Serializable > {
// Implementation omitted
}
Cheers,
Don
Java generics does not support union types (this parameter can be A OR B).
On a related note that may be of interest to some, it does support multiple bounds, if you want to enforce multiple restrictions. Here's an example from the JDK mentioned in the Java generics tutorial:
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
You could use factory methods for all supported types and make the constructor private/protected. You have to fix the generic type in the constructor anyway so that it makes sense, so you could probably code it like this:
public final class MyClass<T> {
public static MyClass<Integer> newInstance(int i) {
return new MyClass<Integer>(i);
}
public static MyClass<String> newInstance(String s) {
return new MyClass<String>(s);
}
//More factory methods...
protected MyClass(T obj) {
//...
}
}
Or if you do not want the constructor parameter, something like this:
public final class MyClass {
public static MyClass newIntegerInstance() {
return new MyClass();
}
//...
}
As erickson stated, the common implementation can rely only on Object anyway, so the only restriction is, that you can create other implementations for other types besides the primitive and String.
While generics won't work here, a base type with derived types for Number and String will. Since a generic type would have erased to Object anyway, any functionality you would have put there can go in an abstract base class. You're likely to need only a type-specific accessor on the subclass to get the value.
Also, be careful with the Number class. It's not limited to boxing the primitive types, as anyone can extend it—e.g., BigInteger.
Interesting question, it boggled me a bit. However apparently this is impossible. I tried several different hacks, none really work.
Maybe you could do what follows:
Make MyClass<T> a package-default class, invisible to other components, or at least with a package-default ctors only, so that it cannot extended or instantiated outside the package.
Create two public classes in the package of MyClass<T>:
MyNumericClass<T extends Number> extends MyClass<T>
MyStringClass extends MyClass<String>
This way all subclasses of MyClass will be limited to those parametrized with a Number subclass or String.