Java how to set objects type - java

For example I have a class which starts like this
public class Class<T> {
private ArrayList<Integer> x = new ArrayList<Integer>();
In main when I do
public class Main {
public static void main(String args[]) {
Class x = new Class();
All elements in x should be of Integer type. How can I do something like Class x = new Integer/String ... Class(); So I can specify the type of the objects in x

You mean something like this?
public class MyClass<T>{
private final List<T> x = new ArrayList<T>();
Now your List is of the generic type given to MyClass.
EDIT
OP in comment - if I want to make a fonction which adds elements to x.
In order to do that you need to create a method (rather than function) that takes an item of type T and adds it to x
public void addThing(final T thing) {
x.add(thing);
}

Use Generics.
public class YourClass<T>{
private ArrayList<T> x = new ArrayList<T>();
Then in Main
public class Main{
public static void main(String args[]){
YourClass<Integer> x = new YourClass<Integer>();
}
or
YourClass<String> x = new YourClass<String>();
YourClass<T> could be then an Integer, String, or whatever.

Class<Integer> x = new Class<Integer>();
Don't use names for classes that are already defined in java.lang package.

I think you are confused by Polymorphism and Generics.
What you want:
Class x = new Integer();
is polymorphism. This statement will only be valid if Class is a base class of Integer, which is clearly not the case.
Parent x = new Child();
will work if
class Child extends Parent {
....
}
The class you have written:
public class Class<T> {
private ArrayList<Integer> x = new ArrayList<Integer>();
....
}
is a generic class but you do not use the type parameter. This is not a problem though, your class will still work. When you say:
Class x = new Class();
The type T will simply be Object. But since you do not use this type parameter, it does not have any effect.
To summarize, your statement of:
Class x = new Integer();
will never work as Integer does not have a "is a" relationship with Class. Generics is not used for this purpose.

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.

class contains one element of subclasses

Giving the diagram below, I want to know the following:
How to make sure that a class car can have a GPS of type A or B not both?
Because of the max multiplicity of 1, all your example diagram is missing is a generalization set that is {complete, disjoint}. Your diagram now says {incomplete, overlapping}, by default, which means an instance can be a member of both A and B, or just a member of GPS.
What about using generics like this:
public class A<T extends B> {
List<T> list = new ArrayList<>();
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
this.list = list;
}
}
public class B {
}
public class C extends B {
}
public class D extends B {
}
Then you will instantiate class A with the desired subtype of B like this:
A<C> a = new A<>();
C c = new C();
D d = new D();
a.getList().add(c); //works fine
a.getList().add(d); //compile error
Taking the fruit basket from your comment, you need to specify a multiplicity for 0..n instead of the 1.
If you want all instances to be the same subclass you need to add a constraint in any way. If your tool does not permit it, just add a note with { all instances ofBmust have the same type } or the like.

class with generic type variable List

I'm reading about generic types. I'm able to understand that generic types can be used to specify the type of content can be consumed by objects or collections to avoid runtime error and solve it while compile time only.
I want to know how can I create a generic class whose type variable(T = List) is List. For example in below example its String.
import java.util.ArrayList;
import java.util.List;
public class Test<T> {
T string;
public Test(T in) {
this.string = in;
}
public static void main(String args[]) {
Test<String> o = new Test<String>("Generic");
}
}
I want to know how can I create a generic class whose type variable(T
= List) is List.
Specify the List as parameterized type.
To have a generic Test of List<String> do for example :
List<String> myList = new ArrayList<>();
...
Test<List<String>> o = new Test<>(myList);
Just déclare your T like an extends of List
Change this:
public class Test<T> {
to this
public class Test<T extends List> {
In this case, you will not be able to write this:
Test<String> o = new Test<String>();
If you want your list strictly to be a list of strings. Then simply declare your list as List<String>
in this way obliges the developer to use a class that belongs to the Collection es (List, ArrayList, Vector, ...)
public class Test<T extends Collection>{ ... }
UPDATE
public class Test<E,T extends Collection<E>>{ ... }

How to create Integer object within a class with Generic Integer

When I tried the following codes, I get an error:
unexpected type
required: class
found: type parameter Integer where Integer is a type-variable
class myClass <Integer>
{
public void myMethod()
{
Integer q = new Integer(5); //Not allowed
}
}
However, the following codes are allowed
class myClass
{
public void myMethod()
{
Integer q = new Integer(5); //Allowed
}
}
Can someone explain why am I not allowed to create Integer object within the class anymore when I declare the class with generic Integer ?
Que: Is it still possible and how to create Integer objects within the class in this case?
You declared Integer to be the generic type parameter, which hides the fact that the class Integer was in scope. You can do one of several things to get around this.
Choose a different name for the generic type parameter, e.g. T.
class myClass<T>
Or, fully-qualify the references to the class Integer.
java.lang.Integer q = new java.lang.Integer(5);
I think you have a wrong idea of what a parametrizable class is.
To declare a parametrizable class:
class myClass <T>
{
T myGenericVariable;
Integer i;
public void myMethod()
{
this.i = new Integer(5);
}
}
How to use it:
myClass mc = new myClass<String>();//String or whatever you want

Instantiate generic type using class passed as parameter

I'm not so experienced with generics and I have a problem.
I have two classes, two generic types, that I have to instantiate passing the same class, so I'm trying to do something like this:
protected MyNotGenericClass(Class<CommonType> myClass) {
g1= new GenericType1<myClass>();
g2 = new GenericType2<myClass>();
}
and pass the CommonType class to the constructor:
new NotAGenericClass(CommonType.class);
but it doesn't work because 'myClass' cannot be resolved to a type.
What I'm doing wrong?
UPDATE
Note that is important for me that NotAGenericClass is not a generic type because I have to instantiate it using Spring and I could find some difficulties.
Try making your class generic, like this:
public class MyClass<T extends CommonType> {
private GenericType1<T> g1 = new GenericType1<T>();
private GenericType2<T> g2 = new GenericType2<T>();
// no constructor needed
}
You need to bubble up the parametric type to the othermost class:
class Foo<T> {
private Bar1<T> g1;
private Bar2<T> g2;
protected Foo(Class<T> clazz) {
g1 = new Bar1<T>();
g2 = new Bar2<T>();
}
}
Note that the only reason to even pass the clazz parameter is if you need to do some reflection-oriented operations at runtime.
Type parameters can only be a Type(Reference Types i., Class type or Interface Type) but not a reference variable.
your code is same as the below code:
String s="12";
List<s> list = new ArrayList<s>();
the above code is illegal as Type Parameters should be the actual Type (Reference Types) , here s is a reference variable but not a type.
same applies to your code .
EDIT:
If you want your constructor to be generic do this:
protected <T> Constructor(T myClass) {
g1= new GenericType1<T>();
g2 = new GenericType2<T>();
}
and your call would be :
new Constructor(new CommonType());
new Constructor(new AnotherCommonType());
You can not use myClass in generics, It is an variable not a class.
example of how to use Generics:
public class GenericExample<T> {
private T genericObject;
public GenericExample(T genericObject){
this.genericObject = genericObject;
}
public T getGenericObject(){
return genericObject;
}
public static void main(String[] args){
GenericExample<String> gen1 = new GenericExample<String>("This is a String");
GenericExample<Integer> gen2 = new GenericExample<Integer>(1);
String format = "value : %s, %s";
System.out.println(String.format(format, gen1.getGenericObject(), gen1.getGenericObject().getClass()));
System.out.println(String.format(format, gen2.getGenericObject(), gen2.getGenericObject().getClass()));
}
}
output:
value : This is a String, class java.lang.String
value : 1, class java.lang.Integer

Categories