Java generics with class and nested static interface - java

I want to use a generic class inside a nested static interface. My objective is to do something like this:
public class MyClass<T>{
private MyInterface task;
public static interface MyInterface{
void aMethod (T item);
}
}
But I get the error: Cannot make a static reference to the non-static type T. If I do some changes (below) I can use a generic type inside an interface, but I want to avoid this method because it's redundant to write the same class 2 times: one for MyClass and one for MyInterface.
public class MyClass<T>{
private MyInterface<T> task;
public static interface MyInterface<T>{
void aMethod (T item);
}
}
Thanks.
EDIT: I want to do this:
MyClass c = new MyClass<String> ();
c.setInterface (new MyClass.MyInterface (){
#Override
public void aMethod (String s){
...
}
);
or
MyClass c = new MyClass<AnotherClass> ();
c.setInterface (new MyClass.MyInterface (){
#Override
public void aMethod (AnotherClass s){
...
}
);

A static nested class or nested interface (which is always static, by the way) has no relation to its outer class (or interface) apart from namespace nesting and access to private variables.
So, the type parameter of the outer class is not available inside the nested interface in your case, you should define it again. To avoid confusion, I recommend using a different name for this inner parameter.
(As an example in the standard API, look for the interface Map.Entry<K,V>, nested inside the interface Map<K,V>, yet has no access to its type parameters and needs to declare them again.)

It's not redundant. With a static interface:
MyClass.MyInterface<String> myInstance;
and with a non-static innter class (an interface is always static):
MyClass<String>.MyInterface myInstance;
A more real world example:
Map<String, Integer> map = ...;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
...
}
The static approach has the advantage that you can import the nested type, and still specify the type parameters:
class ClassWithAReallyLongName<T> {
static interface Entry<T> {
}
}
and
import my.package.ClassWithAReallyLongName.Entry;
class Foo {
Entry<String> bar;
}
though one should use that idiom with caution as to not confuse the reader.

Related

C# generic parent object reference which can take any child [duplicate]

Let's say I have a generic class as follows:
public class GeneralPropertyMap<T>
{
}
In some other class I have a method that takes in an array of GeneralPropertyMap<T>. In Java, in order to take in an array that contains any type of GeneralPropertyMap the method would look like this:
private void TakeGeneralPropertyMap(GeneralPropertyMap<?>[] maps)
{
}
We use the wildcard so that later we can call TakeGeneralPropertyMap passing a bunch of GeneralPropertyMap with any type for T each, like this:
GeneralPropertyMap<?>[] maps = new GeneralPropertyMap<?>[3];
maps[0] = new GeneralPropertyMap<String>();
maps[1] = new GeneralPropertyMap<Integer>();
maps[2] = new GeneralPropertyMap<Double>();
//And finally pass the array in.
TakeGeneralPropertyMap(maps);
I'm trying to figure out an equivalent in C# with no success. Any ideas?
Generics in C# make stronger guarantees than generics in Java. Therefore, to do what you want in C#, you have to let the GeneralPropertyMap<T> class inherit from a non-generic version of that class (or interface).
public class GeneralPropertyMap<T> : GeneralPropertyMap
{
}
public class GeneralPropertyMap
{
// Only you can implement it:
internal GeneralPropertyMap() { }
}
Now you can do:
private void TakeGeneralPropertyMap(GeneralPropertyMap[] maps)
{
}
And:
GeneralPropertyMap[] maps = new GeneralPropertyMap[3];
maps[0] = new GeneralPropertyMap<String>();
maps[1] = new GeneralPropertyMap<Integer>();
maps[2] = new GeneralPropertyMap<Double>();
TakeGeneralPropertyMap(maps);
While, as others have noted, there's no exact correspondence to wildcards in c#, some of their use cases can be covered with covariance/contravariance.
public interface IGeneralPropertyMap<out T> {} // a class can't be covariant, so
// we need to introduce an interface...
public class GeneralPropertyMap<T> : IGeneralPropertyMap<T> {} // .. and have our class
// inherit from it
//now our method becomes something like
private void TakeGeneralPropertyMap<T>(IList<IGeneralPropertyMap<T>> maps){}
// and you can do
var maps = new List<IGeneralPropertyMap<Object>> {
new GeneralPropertyMap<String>(),
new GeneralPropertyMap<Regex>()
};
//And finally pass the array in.
TakeGeneralPropertyMap<Object>(maps);
The caveat is that you can't use covariance with value types, so adding a new GeneralPropertyMap<int>() to our list fails at compile time.
cannot convert from 'GeneralPropertyMap<int>' to 'IGeneralPropertyMap<object>'
This approach may be more convenient than having a non-generic version of your classes/interfaces in case you want to constrain the types that GeneralPropertyMap can contain. In that case:
public interface IMyType {}
public class A : IMyType {}
public class B : IMyType {}
public class C : IMyType {}
public interface IGeneralPropertyMap<out T> where T : IMyType {}
allows you to have:
var maps = new List<IGeneralPropertyMap<IMyType>> {
new GeneralPropertyMap<A>(),
new GeneralPropertyMap<B>() ,
new GeneralPropertyMap<C>()
};
TakeGeneralPropertyMap(maps);
There is no direct equivalent to this in C#.
In C#, this would often be done by having your generic class implement a non-generic interface or base class:
interface IPropertyMap
{
// Shared properties
}
public class GeneralPropertyMap<T> : IPropertyMap
{
}
You could then pass an array of these:
IPropertyMap[] maps = new IPropertyMap[3];
// ...
TakePropertyMap(maps);
Make an interface from the members of GeneralPropertyMap (IGeneralPropertyMap), and then take an IGeneralPropertyMap[] as an argument.
Actually, you can get pretty close to a wildcard by using dynamic. This also works nicely if you have a non-generic superclass.
For example:
public class A
{
// ...
}
public class B<T> : A
{
// ...
}
public class Program
{
public static A MakeA() { return new A(); }
public static A MakeB() { return new B<string>(); }
public static void Visit<T>(B<T> b)
{
Console.WriteLine("This is B with type "+typeof(T).FullName);
}
public static void Visit(A a)
{
Console.WriteLine("This is A");
}
public static void Main()
{
A instA = MakeA();
A instB = MakeB();
// This calls the appropriate methods.
Visit((dynamic)instA);
Visit((dynamic)instB);
// This calls Visit(A a) twice.
Visit(instA);
Visit(instB);
}
}
How this works is explained in the C# documentation here.

Java Generics initialization of child class in base class

I'm pretty new to java and not particularly sure how to initialize a generic type / child class from the 'base' class.
Essentially I have a bunch of classes that extend the abstract class BaseClass that need to be initialized and added to the instance Map if a key is not present.
The child class is re-used multiple times but is dynamically created based on the key parameter.
I would like to avoid reflection and don't mind changing the template if it's not 'the Java way'.
What I currently have:
public abstract class BaseClass<T> {
protected Map<String, T> instance = new HashMap<String, T>();
public T Get(String key) {
if (this.instance.containsKey(key)) {
return this.instance.get(key);
}
T item = new T(key); // Obviously this line errors but you get the idea
instance.put(key, item);
return item;
}
}
// Example top class which extends my base class
public class TopClass extends BaseClass<TopClass> {
public TopClass(String key) {
// Do unique initialization stuff
}
}
Since generic types are erased at runtime, you cannot do this. You can instead use a Class variable as follows:
public T Get(Class<T> clazz, String key) throws Exception {
if (this.instance.containsKey(key)) {
return this.instance.get(key);
}
T item = clazz.getDeclaredConstructor(String.class).newInstance(key);
instance.put(key, item);
return item;
}
I have another approach to this.
Have an interface MyInterface.
public interface MyIinterface{
public void doSomething();
}
Create an many implementations of this interface.
#Component
public class MyImplementation1 implements MyInterface{
#Override
public void doSomething(){
}
}
Use spring core jars in the dependency.
Annotate all the implementations with #Component.
#Component
public class MyImplementation1 implements MyInterface{
.
.
Have a method in some Util class that will get you the implementation based on a string key.
public static MyInterface getImplementation(String name){
ApplicationContext context;
return context.getBeanByName(name);
}

instantiate object of abstract class with generic type

I am creating a function with a generic type and that generic type is an abstract type which I need to instantiate. This code will explain it more clearly:
public <T extends AbstractRow> foo(){//no I did not actually name the function foo
ArrayList<T> arr=new ArrayList<T>();
arr.add(new T(...)); //cant instantiate objects of abstract class
}
Basically I want to enforce "T extends AbstractRow but is not Abstract itself".
I realize you can't instantiate abstract classes, so I'd like a suggestion on a workaround or some other method that would allow me to mimic the behavior of creating an object of a generic type.
As far as I know, there's two ways to do this:
Add a Class<T> type field to your abstract generic class, and set it through the constructor (or another method). You can then invoke type.newInstance() to create the object.
Create a factory interface Factory<T> with a T create() method and set that as a field on your abstract class through the constructor (or another method). Upon creating a concrete instance of your generic class, you also have to pass a concrete implementation of said factory.
import java.util.ArrayList;
import java.util.List;
public class Generic<T> {
private Factory<T> factory;
public Generic(Factory<T> factory) {
this.factory = factory;
}
public void foo() {
List<T> list = new ArrayList<>();
list.add(factory.create());
}
}
interface Factory<T> {
T create();
}
Usage:
Generic<Bar> concrete = new Generic<>(new Factory<Bar>() {
#Override
public Bar create() {
return new Bar();
}
});
concrete.foo();
Your main issue isn't that you're working with an abstract class - in which case the suggestions posted in the comments would be useful. The bigger problem is that you're trying to instantiate a generic type directly (read: new T()) - which, simply put, you can't do in Java because of type erasure.
That said, there's always a workaround:
/**#param clazz the subclass you want to instantiate */
public <T extends AbstractRow> foo(Class<T> clazz) {
ArrayList<T> arr = new ArrayList<T>();
arr.add(clazz.newInstance); //instantiate new instance of given subclass
}
Usage:
abstract class Test1 {}
class Test2 extends Test1{ }
class Test<T> {
public static <T extends Test1> T foo(Class<T> clazz) {
T toReturn = null;
try{ toReturn = clazz.newInstance(); } catch (Exception e) { };
return toReturn ;
}
public static void main(String[] args) {
Test1 t1 = t.foo(test2.class);
System.out.println(t1.getClass()); //prints "class pkgname.test2"
}
}

Java - Generic Static Methods

I have been trying to understand whether it is possible to make a method which infers a generic type based on the return class and calls a static method of that generic type.
i.e. Below I create 2 classes both of which implement the getInstances and getAllInstances methods. I then attempt to create use the methods from a generic wrapper. It appears that the super class method is always being run regardless of the return type.
For example,
public class ParentClass {
public ParentClass(){}
public static <T extends ParentClass> T getInstance(){
return (T) new ParentClass();
}
public static <T extends ParentClass> List<T> getAllInstances(){
ArrayList<ParentClass> parents = new ArrayList<ParentClass>();
for(int i=0;i<5;i++){
parents.add(new ParentClass());
}
return (List<T>) parents;
}
}
SubclassA
public class SubclassA extends ParentClass{
public SubclassA(){}
#SuppressWarnings("unchecked")
public static SubclassA getInstance(){
return new SubclassA();
}
#SuppressWarnings("unchecked")
public static List<SubclassA> getAllInstances(){
ArrayList<SubclassA> parents = new ArrayList<SubclassA>();
for(int i=0;i<5;i++){
parents.add(new SubclassA());
}
return parents;
}
}
Wrapper - Shows the problem
public class Wrapper {
public Wrapper(){
// ... some other stuff
}
public <T extends ParentClass> T getInstance(){
return T.getInstance();
}
public <T extends ParentClass> List<T> getAllInstances(){
return T.getAllInstances();
}
public static void main(String... args){
Wrapper wrapper = new Wrapper();
SubclassA subclassA = wrapper.getInstance();
ParentClass parentClass = wrapper.getInstance();
System.out.println(subclassA.getClass().getName());
System.out.println(parentClass.getClass().getName());
}
}
When running Wrapper I get the following error:
Exception in thread "main" java.lang.ClassCastException: ParentClass cannot be cast to SubclassA
at Wrapper.main(Wrapper.java:20)
Can I do this in Java?
static methods will not be override.This static methods will belongs to Class level
Your approach is incorrect, there is no notion of static Inheritance in Java as inheritance always is in context of Object level. Only member methods (non-static) can be inherited by sub classes having appropriate access modifiers.
Update:
Further to add, in your scenario Factory pattern seems more suitable than adjusting generics for getting/constructing specific class objects.
No, you can't do it like this. To make it work you can pass the Class object:
public class ParentClassUtils
public static <T extends ParentClass> T getInstance(Class<T> clazz) {
return clazz.newInstance();
}
public static <T extends ParentClass> List<T> getAllInstances(Class<T> clazz) {
List<T> list = new ArrayList<T>();
for (int i = 0; i < 5; i++) {
list.add(getInstance(clazz));
}
return list;
}
}
Also, in your example you have equivalent static methods in parent classes and subclasses. The subclass methods don't override the parent class methods, they merely hide them, and this almost certainly isn't what you want. This utility class approach above gets around this.

Declare attribute of type that extends 2 different interfaces

I would like to declare attribute that holds instance of class that implements 2 different interfaces. I have tried this syntax:
private <? extends Interface1 & Interface2> name;
and this:
private <T extends Interface1 & Interface2> T name;
None of those work. Is it possible? What's the syntax? I'm trying to avoid declaring another interface that inherits from both Interface1 and Interface2.
Edit:
The class containing this attribute should not have any type arguments. That is nothing like this:
public class MyClass<T extends Interface1 & Interface2>{
private T name;
...
}
It would not make any sense for those using the class. It is not expected neither logical not possible for that class to be generic.
That needs to go in the class declaration, such as:
public class TestG<T extends Cloneable & Serializable> {
private T name;
}
One alternative is to set it in a method (but not a variable)
public class TestG {
public <T extends Cloneable & Serializable> void method(T parameter) {
}
}
A variable cannot be generic.
private <T> T var;
is not possible - at which point is T defined? When accessing var, I cannot make much assumptions on what I used at assignment time.
Java allows generics on classes and on methods. So you can have
private <T implements Cloneable & Serializable> void setVar(T val);
and you can have a class-wide type T.
But always remember that in the end, it is implemented by type erasure. You can always emulate more complex logic using getters, setters and casts. When done properly, it will give you just as much type safety.
The simplest way to obtain a variable with the type safety you want is to just use two variables, and a setter to keep them in sync.
private Serializable vars;
private Cloneable vars;
will of course give you a good type safety. But yes, it needs 4 bytes of additional memory, and a setter.
Here's the casting approach you asked:
private Object internal_var;
// Implementation notice: do not remove this generic.
// Due to a Java limitation, we *do* want these two constraints!
public <T extends Serializable & Cloneable> void setVar(T val) {
internal_var = val;
}
public Serializable getSerializable() {
return (Serializable) internal_var; // Type checked in setter!
}
public Cloneable getCloneable() {
return (Cloneable) internal_var; // Type checked in setter!
}
// This is the way to use it in a generic getter:
public <T extends Serializable & Cloneable> T getVar(Class<? super T> cls) {
return (T) cls.cast(val);
}
Note that in order to use T in the getter, we do need to have a parameter involving T.
Assuming we know a class Example implements Serializable, Cloneable, we can then use
// This actually ensures we get an instance of `Example` out:
Example e = instance.getVar(Example.class);
You can declare that type parameter in your class declaration, or method declaration, if that is a local variable, and use that type instead: -
public class Demo<T extends Interface1 & Interface2> {
private T t;
}
or: -
public class Demo {
public <S extends Interface1 & Interface2> void demo(S param1) {
S param;
}
}
If i understand your question correctly, you want a generic class which implements both the inetrfaces.
declare a generic type argument in your class definition and make it as an instace variable type.
public class Implementor<T extends Interface1<T> & Interface2<T>> {
private T t;
}
EDIT:
you cannot declare a type argument at instance variable declaration like
private <T extends I1 &I2> T t; //this cant be achieved.
at method level though is possible.
public <T extends I1 & I2> void method(T t){
}

Categories