In C# I can do actually this:
//This is C# static T SomeMethod<T>() where T:new() { Console.WriteLine("Typeof T: "+typeof(T)); return new T(); } //And call the method here SomeMethod<SomeClassName>();
But for some reason I can't get it to work in Java.
The thing I want to do is, to create a static method on a superclass, so the subclasses can be converted to XML.
//This is Java, but doesn't work public static T fromXml<T>(String xml) { try { JAXBContext context = JAXBContext.newInstance(T.class); Unmarshaller um = context.createUnmarshaller(); return (T)um.unmarshal(new StringReader(xml)); } catch (JAXBException je) { throw new RuntimeException("Error interpreting XML response", je); } } //Also the call doesn't work... fromXml<SomeSubObject>("<xml/>");
Yes, you can define a generic method in a non-generic class in Java.
Which of the following allows us to call generic methods as a normal method? Explanation: Type inference, allows you to invoke a generic method as an ordinary method, without specifying a type between angle brackets.
For static generic methods, the type parameter section must appear before the method's return type. The complete syntax for invoking this method would be: Pair<Integer, String> p1 = new Pair<>(1, "apple"); Pair<Integer, String> p2 = new Pair<>(2, "pear"); boolean same = Util. <Integer, String>compare(p1, p2);
Java Generic methods and generic classes enable programmers to specify, with a single method declaration, a set of related methods, or with a single class declaration, a set of related types, respectively. Generics also provide compile-time type safety that allows programmers to catch invalid types at compile time.
public static <T> T fromXml(Class<T> clazz, String xml) {
Called as:
Thing thing = fromXml(Thing.class, xml);
or more explicitly:
Thing thing = MyClass.<Thing>fromXml(Thing.class, xml);
To be even more confusing you can have constructors that both construct a generic type and have a generic parameter themselves. Can't remember the syntax and have never seen it used in anger (you are probably better off with a static creation method anyway).
The cast (T)
is unsafe, and you can't write T.class. So include the T.class as an argument (as JAXBContext.newInstance
does) and throw a relevant exception if the type is wrong.
public static <T> T fromXml(Class<T> clazz, String xml) { try { JAXBContext context = JAXBContext.newInstance(clazz); Unmarshaller um = context.createUnmarshaller(); Object obj = um.unmarshal(new StringReader(xml)); try { return clazz.cast(obj); } catch (ClassCastException exc) { throw new RelevantException( "Expected class "+clazz+ " but was "+obj.getClass() ); } } catch (JAXBException exc) { throw new RelevantException( "Error unmarshalling XML response", exc ); } }
I believe the next version of JAXB (in 6u14?) has some convenience methods for this sort of thing in the JAXB
class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With