I have problem with comparing java generic type if it is type of Void or not. In other words I'm trying to ensure if my generic type T is Void or not.
My sample implementation:
public abstract class Request<T>{
private T member;
protected void comparing(){
if(T instanceof Void) // this make error "Expression expected"
runAnotherMethod();
//if I type
if(member instanceof Void) //Incovertible types; cannot cast T to java.lang.Void
runAnotherMethod();
}
protected void runAnotherMethod(){...}
}
public class ParticularRequest extends Request<Void>{
}
I've tried to compare id via instanceof, Class<T> and Class<Void>, T.class and Void.class.
But the AndroidStudio show me error in every tried case :(
can you help me how to compare it?
thanks.
When using java generics you often need to ask for the class of the generic type in the constructor so that you can actually work with the class. I guess, that is a confusing sentence so just see the example below:
public abstract class Request<T> {
private Class<T> clazz;
// constructor that asks for the class of the generic type
public Request(Class<T> clazz) {
this.clazz = clazz;
}
// helper function involving the class of the generic type.
// in this case we check if the generic type is of class java.lang.Void
protected boolean isVoidRequest(){
return clazz.equals(Void.class);
}
// functionality that depends on the generic type
protected void comparing() {
if (isVoidRequest()) {
runAnotherMethod();
}
}
// ...
}
When you subclass you must pass the class of the generic type to the super constructor.
public class LongRequest extends Request<Long> {
public LongRequest() {
super(Long.class);
}
}
public class VoidRequest extends Request<Void> {
public VoidRequest() {
super(Void.class);
}
}
You can store a private member that is of the generic type of the class.
public abstract class Request<T> {
private T memberOfGenericType;
protected void comparing() {
if (memberOfGenericType instanceof Sometype)
runAnotherMethod();
}
protected void runAnotherMethod() { ... }
public T getMemberOfGenericType() {
return memberOfGenericType;
}
public void setMemberOfGenericType(T value) {
this.memberOfGenericType = value;
}
}
This way, at Runtime, the memberOfGenericType will have the type of Sometype and you will be able to compile the if statement. You can also verify that the memberOfGenericType is Sometype at Runtime, by using the getter I've added.
Anyhow, as a side note, I would say that there's no need of generic type, if you don't use it as a type for a member, method or method parameter and then you should re-consider your design. Also, in particular, the type Void is not instantiable, so you wouldn't be able to pass a valid instance for the class member, which more or less makes the if statement useless.
You can't use T like that. You need some instance to compare. For example some member or parameter:
public abstract class Request<T> {
T member;
protected void comparing(T param){
if(member instanceof Void)
runAnotherMethod();
if(param instanceof Void)
runAnotherMethod();
}
protected void runAnotherMethod(){...}
}
A better approach to accessing the parameter class, used by Guice, is to use the fact that, while a generic class cannot access its own 'class' arguments, its subclasses do have access to these arguments: see https://stackoverflow.com/a/18610693/15472
If you need this, either use Guice' TypeLiterals, or reimplment their logic.
Since there are no objects that are instances of the Void type in Java you can't use instanceof here.
null is the only value that is a member of the type Void. So maybe what you want to do is this?:
if (memberOfGenericType == null)
runAnotherMethod();
About the type Void
No objects of type Void can be created because the class only has a private constructor and it is never invoked from within the class. Void is usually used in these situations:
To get a Class object that represents the return type of methods declared to return void.
As a placeholder type argument, when the fields and variables of that type are not meant to be used.
At run-time T is compiled as Object, and the actual class is unknown. As others said, you should maintain an instance of your parametrized type, but this is not automatic: You need to instantiate it, and the constructor T() cannot be used.
Also java.lang.Void cannot be instantiated, so you should use another class, like a self-made Void class.
Try something like this:
public final class Void {}; // cannot use java.lang.Void, so create another class...
public abstract class Request<T> {
protected abstract T member(); // A member would need to be initialized...
protected void comparing(T param){
if(member() instanceof Void) // Use our Void not java.lang.Void
runAnotherMethod();
}
protected void runAnotherMethod(){...}
}
public class ParticularRequest extends Request<Void>{
#Override
protected Void member() { return new Void(); } // Could be optimized...
}
Edit:
I do not see, why would you need this, however.
If you have different children for different types, then you also could have different implementations, too.
Something like this (types and methods are for example only):
public abstract class Request<T> {
protected abstract T method();
}
public class RequestInt extends Request<Integer> {
#Override
protected Integer method() {...}
}
public class RequestText extends Request<String> {
#Override
protected String method() {...}
}
Related
I'm primarily a Java programmer, so this would be one of those "what is this thing from Java equivalent to in C#" questions. So, in Java, you can restrain a Class type argument at compile time to extend a certain super-class, like so:
public <T extends BaseClass> void foo(Class<T> type) {
...
}
and even
public <T extends BaseClass> T foo(Class<T> type) {
...
}
You can even chain multiple interfaces:
public <T extends BaseClass & BaseInterface1 & BaseInterface2> void foo(Class<T> type) {
...
}
How is this done in C#? I know you can use "where T : BaseClass", but this is only applicable when you have an instance T. What about when you only have a Type instance?
EDIT:
For explanation, here is what I would like to do:
ASSEMBLY #1 (base.dll):
abstract class BaseClass {
abstract void Foo();
}
ASSEMBLY #2 (sub1.dll, references base.dll):
class SubClass1 : BaseClass {
void Foo() {
// some code
}
}
ASSEMBLY #3 (sub2.dll, references base.dll):
class SubClass2 : BaseClass {
void Foo() {
// some other code
}
}
ASSEMBLY #4 (main.dll, references base.dll):
class BaseClassUtil {
static void CallFoo(Type<T> type) where T : BaseClass {
T instance = (T)Activator.CreateInstance(type);
instance.Foo();
}
}
public static void Main(String[] args) {
// Here I use 'args' to get a class type,
// possibly loading it dynamically from a DLL
Type<? : BaseClass> type = LoadFromDll(args); // Loaded from DLL
BaseClassUtil.CallFoo(type);
}
So, in this example, I don't care what class the 'type' variable represents, as long as it is derived from BaseClass, so once I create an instance, can call Foo().
The parts that are not vaild C# code (but rather some Java mockup) are the "generic" Type classes: Type<T> and Type<? : BaseClass>.
No, there is no way to enforce at compile time that a Type be assignable to a generic type. If I understand correctly, what you want is:
void Foo<T>(Type type) { ... } //compile time error if an instace typed `type` is not assignable to `T`.
Which means:
void Foo<IFormattable>(typeof(string)); //ok
void Foo<IDisposable>(typeof(string)); //compile time error
Evidently at runtime it is trival, but the language has no support for this at compile time.
From what I understood you are talking about generic type constraint
public void Foo<T>(Type type) where T:BaseClass, BaseInterface1, BaseInterface2
{
//your code
}
Here another article:Constraints on Type Parameters (C# Programming Guide)
When you define a generic class, you can apply restrictions to the
kinds of types that client code can use for type arguments when it
instantiates your class. If client code tries to instantiate your
class by using a type that is not allowed by a constraint, the result
is a compile-time error.
EDIT:
Here your example. Now if you try to call BaseClassUtil.CallFoo<T> with something different from BaseClass and his derived classes you will receive an compile error. Here full example in dotNetFiddle. So the tricky part is the restriction of your class should happen in the Util class
public static void Main(string[] args)
{
//so your LoadFromDll method should return Type. Type doesn't have generic implementation !
Type type = typeof(SubClass1);
BaseClassUtil.CallFoo<BaseClass>(type);
Type type2 = typeof(SubClass2);
//you can write BaseClassUtil.CallFoo<SubClass2>(type2); if you want
BaseClassUtil.CallFoo<BaseClass>(type2);
}
public class BaseClassUtil
{
public static void CallFoo<T>(Type type) where T : BaseClass
{
T instance = (T)Activator.CreateInstance(type);
instance.Foo();
}
}
public class TestClass
{
public int ID { get; set; }
}
public abstract class BaseClass
{
public abstract void Foo();
}
public class SubClass1 : BaseClass
{
public override void Foo()
{
Console.WriteLine("SubClass 1");
}
}
public class SubClass2 : BaseClass
{
public override void Foo()
{
Console.WriteLine("SubClass 2");
}
}
I got a generic interface with one method accepting a parameter of the generic type:
public interface ComponentRenderer<T extends GuiComponent> {
public void draw(T component);
}
Furthermore I have an abstract class, that declares a variable of this interface type using a bounded wildcard:
public abstract class GuiComponent extends Gui {
private ComponentRenderer<? extends GuiComponent> componentRenderer;
public void draw() {
this.componentRenderer.draw(this);
}
//and a setter and getter for the ComponentRenderer
}
And a subclass, wich set a implementation for the componentRenderer:
public class GuiButton extends GuiComponent {
public GuiButton(/* ... */) {
//...
this.setComponentRenderer(new FlatButtonRenderer());
}
where FlatButtonRenderer is implemented as:
public class FlatButtonRenderer implements ComponentRenderer<GuiButton> {
#Override
public void draw(final GuiButton component) {
//...
}
}
I can't see where I got something wrong, but the call componentRenderer.draw(this) in GuiComponent does not work with the following error:
As far as I understand this, it says me, that I can't use GuiComponent because it does not derive from GuiComponent, what makes no sense. I've also tried ? super GuiComponent, which will accept the draw() call, but then does not accept the implementation of FlatButtonRenderer
I do not understand this syntax error, does anyone have an idea, how I need to change the code?
EDIT:
When I use my IDE's code completion on the call of draw(), it says me, that draw accept one argument of type "null", so for some reason, it is not able to figure out, wich type the argument should be...
The problem is that ? extends GuiComponent means "one specific subtype of GuiComponent, but unknown which".
The compiler does not know that this is of the right GuiComponent subtype for the ComponentRenderer. It could be that the renderer only can work with some other specific subclass.
You have to use some kind of self-type pattern to do this in a type-safe way. That way you kind of "connect" the type variable of the renderer with the type of the GuiComponent subclass.
Example:
class Gui {}
interface ComponentRenderer<T extends GuiComponent<T>> {
public void draw(T component);
}
// T is the self-type. Subclasses will set it to their own type. In this way this class
// can refer to the type of its subclasses.
abstract class GuiComponent<T extends GuiComponent<T>> extends Gui {
private ComponentRenderer<T> componentRenderer;
public void draw() {
this.componentRenderer.draw(thisSub());
}
public void setComponentRenderer(ComponentRenderer<T> r) {}
// This method is needed for the superclass to be able to use 'this'
// with a subclass type. Sub-classes must override it to return 'this'
public abstract T thisSub();
//and a setter and getter for the ComponentRenderer
}
// Here the self-type parameter is set
class GuiButton extends GuiComponent<GuiButton> {
public GuiButton(/* ... */) {
//...
this.setComponentRenderer(new FlatButtonRenderer());
}
class FlatButtonRenderer implements ComponentRenderer<GuiButton> {
#Override
public void draw(final GuiButton component) {
//...
}
}
#Override
public GuiButton thisSub() {
return this;
}
}
This is originally (I think) called the curiously recurring template pattern. This answer explains it more.
In GuiComponent, change your declaration of componentRenderer to this:
ComponentRenderer<GuiComponent> componentRenderer;
I don't understand the following code:
public class EventAdapter extends ArrayAdapter<Event>
{
public EventAdapter(Context context, int textViewResourceId,
List<Event> objects)
{
super(context, textViewResourceId, objects);
this.resource = textViewResourceId;
}
}
I am confused about the <Event> part in both cases. I understand it has something to do with Generics, but I don't understand it. I read http://docs.oracle.com/javase/tutorial/java/generics/, but still don't understand.
I do understand that objects is an ArrayList of objects of the type Event.
The part I don't understand is extending an ArrayAdapter with the Type <Event>. What does this signify?
extends ArrayAdapter<Event>
The type restriction here will influence on the return types of methods in the class, and the argument types of methods.
Here is an example, if you have a class:
class SomeClass<T> {
protected T value;
public void setValue (T value) {
this.value = value;
}
public T getValue () {
return value;
}
}
And if you have another class:
class SubClass extends SomeClass {
#Override
public void setValue (Event value) { // Fail! It is not overriding the super class' method.
this.value = value; // Warning! Unchecked types (maybe inconsistent).
}
}
If you remove the #Override annotation, it will run. But the extends SomeClass is useless and might cause problem if you keep it there -- there will be two very similar methods: setValue(Event) and super.setValue(T). Now the question is will the subclass have access to the super.setValue(T) method? I will explain it in the end, see "A missing type parameter bounding example".
So, you need to specify the type in declaration:
class SubClass extends SomeClass<Event> {
#Override
public void setValue (Event value) { // Correct now!
this.value = value;
}
}
Also, if you declare an inconsistent type:
class SubClass extends SomeClass<String> {
#Override
public void setValue (Event value) { // Fail! Not overriding.
this.value = value; // Fail! Inconsistent types.
}
}
So the type restricts the behavior of class body.
A missing type parameter bounding example:
import java.lang.reflect.*;
class Super<T> {
public void method (T t) {
System.out.println("Hello");
}
public void method2 () {
}
}
public class Test extends Super {
/*public void method (Object t) {
System.out.println("world");
}*/
/*public <T> void method (T t) {
}*/
public static void main (String args[]) {
new Test().method("");
for (Method m : Test.class.getMethods()) {
System.out.println(m.toGenericString());
}
}
}
If I comment method() in the subclass, it is compiled with a warning: Test.java uses unchecked or unsafe opertations. In the running result, it turned the generic type T into Object: public void Test.method(java.lang.Object).
If I only uncomment the first method() in the subclass, it is compiled with no warnings. In the running result, the subclass owns one public void Test.method(java.lang.Object). But it doesn't allow #Override annotation.
If I only uncomment the second method() in the subclass (which also has a generic type bounding), the compile fails with an error: name clash. It also doesn't allow #Override annotation. If you do so, it throws a different error: method does not override.
method2() is inherited by the subclass unanimously. But you also can't write the following code:
in superclass: public void method2 (Object obj) and in subclass: public <T> void method2 (T obj). They are also ambiguous and is not allowed by the compiler.
Here's my simplistic way of looking at generics in this case. Given the definition:
public class EventAdapter extends ArrayAdapter<Event>
I read it as: "An EventAdapter IS-A ArrayAdapter OF Event objects."
And I take List<Event> objects to mean a List of Event objects.
Collections are containers for objects, while Generics define what they can contain.
This assigns a value for the generic parameter in ArrayAdapter in a way that takes away control from the user of the EventAdapter class.
Any method overriding here can then replace T with Event and Event can be used inplace of T without casts.
This is the general definition of generics.
That this is allowed in this case is defined in the spec. While the exact behaviour is not defined in that section I think it is in line with all other generic behaviour as far as I can see.
While I see the construct here the first time, after some thinking it really isn't anything unusual.
(Working in Java)
I have an abstract class with generic typing throughout the whole class:
public abstract class ConnectionProcessor<T>
{
public void process()
{
for (List<T> resultsPage : connection)
{
processPage(resultsPage);
}
}
protected abstract void processPage(List<T> resultsPage);
}
I have another class that extends said abstract class, with the following declaration:
public class AlbumProcessor<Album> extends ConnectionProcessor
{
#Override
protected void processPage(List resultsPage)
{
//Do stuff here specific to Album
}
}
This declaration works fine, but in processPage I want to do Album-specific things, and I try to avoid casting when I don't need to use it. I would PREFER this to be the method declaration:
protected void processPage(List<Album> resultsPage)
But this doesn't meet the requirements for overriding processPage from ConnectionProcessor. Why is this? How can I get the desired behavior? I would think that in AlbumProcessor I could just plug in <Album> everywhere ConnectionProcessor has <T>, but that just isn't the case.
Try
//extend prameterized version of ConnectionProcessor<T> with Album as actual type argument
public class AlbumProcessor extends ConnectionProcessor<Album> {
instead of
public class AlbumProcessor<Album> extends ConnectionProcessor {
When you do the above you are exteding the raw version of the generic type ConnectionProcessor<T> and introducing a new formal type parameter - Album (like T) which is not an actual type argument in that case.
That's because you didn't bind your super class Generic type T to Album.
Rather, this is what you should do:
public class AlbumProcessor extends ConnectionProcessor<Album>
So, when you'll override your method processPage, (using an IDE), it will generate code as follows:
#Override
protected void processPage(List<Album> resultsPage)
{
//Do stuff here specific to Album
}
public class AlbumProcessor extends ConnectionProcessor<Album>
Try: -
public class AlbumProcessor extends ConnectionProcessor<Album>
{
#Override
protected void processPage(List<Album> resultsPage)
{
//Do stuff here specific to Album
}
}
You need to bind your super class with the type you want to give as a type parameter to your List in your method declaration..
How bout something more like this.
import java.util.List;
public abstract class ConnectionProcessor<T>
{
public void process()
{
System.out.println("Hello");
}
protected abstract void processPage(List<? extends T> resultsPage);
}
...
public class ProcessorImpl extends ConnectionProcessor<Album> {
protected void processPage(List<? extends Album> resultsPage) {
for(Album result : resultsPage){
System.out.println(result.getAlbumName());
}
}
}
...
public class Album {
public String getAlbumName(){
return "Sweet Smooth SOunds of the 70's";
}
}
I have some troubles with a method having a typed List parameter, inherited from another (typed) class.
Let's keep it simple :
public class B<T> {
public void test(List<Integer> i) {
}
}
The B class has a useless generic T, and test() want an Integer List.
Now if I do :
public class A extends B {
// don't compile
#Override
public void test(List<Integer> i) {
}
}
I get a "The method test(List) of type A must override or implement a supertype method" error, that should not happen.
But removing the type of the list works... although it doesn't depend on the class generic.
public class A extends B {
// compile
#Override
public void test(List i) {
And also defining the useless generic below to use the typed list
public class A extends B<String> {
// compile
#Override
public void test(List<Integer> i) {
So I'm clueless, the generic of B should have no influence on the type of the test() list. Does anyone have an idea of what's happening?
Thanks
You're extending the raw type of B, not the generic one. The raw one effectively does not have a test(List<Integer> i) method, but a test(List) method.
If you switch to raw types, all generics are replaced by raws, regardless of whether their type was filled in or not.
To do it properly, do
public class A<T> extends B<T>
This will use the generic type B<T>, which includes the method you want to override.
When you remove use a class without generics (and use it raw), all generics from class methods are forgotten.
Due this reason when you inform the generic type on the second case you get it working.
This:
class T<G> {
public void test(G g);
}
in this case:
class A extends T {
}
will look like this:
class T {
public void test(Object g);
}
This was a java puzzle presented on Google IO 2011 you can see video here