开发者

How to write a generic method in Java

How to write a generic method in Java.

In C# I would do this

    public static T Resolve<T>()
 开发者_开发技巧   {
        return (T) new object();
    }

Whats the equivalent in Java?


First, your C# example is wrong; it will throw an InvalidCastException unless typeof(T) == typeof(object). You can fix it by adding a constraint:

public static T Resolve<T>() where T : new() {
    return new T();
}

Now, this would be the equivalent syntax in Java (or, at least, as close as we can get):

public static <T> T Resolve() {
    return (T) new T();
}

Notice the double mention of T in the declaration: one is the T in <T> which parameterizes the method, and the second is the return type T.

Unfortunately, the above does not work in Java. Because of the way that Java generics are implemented runtime type information about T is not available and so the above gives a compile-time error. Now, you can work around this constraint like so:

public static <T> T Resolve(Class<T> c) {
    return c.newInstance();
}

Note the need to pass in T.class. This is known as a runtime type token. It is the idiomatic way of handling this situation.


As other commenters have pointed out, you can do this with Java as well - with as much of a possibility to create a casting exception at runtime:

@SuppressWarnings("unchecked")
public static <T> T resolve() {
  return (T) new Object();
}

Unless you use the @SuppressWarnings annotation, however, Java's type erasure comes into play and you will get a compiler warning. The exception will also occur somewhere else: whereever you are trying to use it:

String s = <String>resolve();

will throw the exception.

On the other hand, you probably wanted to use new T() in C# anyway. This you cannot do in Java. The suggested workaround is to use Class<T> as a type parameter if you need to rely on type information at runtime. For your example, this would mean that you have to refactor it to this version:

public static <T> T resolve(Class<T> type) {
  try {
    return type.newInstance();
  } catch(Exception e) {
    // deal with the exceptions that can happen if 
    // the type doesn't have a public default constructor
    // (something you could write as where T : new() in C#)
  }
}

By the way, you can use this also to get rid of the warning in the previous case and to place the runtime exception at a more sensible line:

public static <T> T resolve(Class<T> type) {
  return type.cast(new Object());
}

This piece of code will behave exactly like the one you gave as an example - including an exception that occurs when T is any type different from Object.


Try this http://java.sun.com/docs/books/tutorial/extra/generics/methods.html

 public static <T> T Resolve()
    {
        return (T) new Object();
    }

Be careful about (T) but I am not sure that this is correct. I know that generic cast causes a lot of problems. I have already spent with it a lot of time...


You want some kind of factory:

 public interface MyFactory<T> {
     T newInstance();
 }

Then that can be passed into where it is needed. In your code:

public static T resolve<T>(MyFactory<T> factory) {
    return factory.newInstance();
}

Note: There is absolutely no reason to be using reflection for this!!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜