Inheritance in Java that doesnt lose data - java

Can i storage all my inherited objects as ArrayList? I dont want to create new ArrayList for each object type something like:
ArrayList<MyObjectTypeA>
ArrayList<MyObjectTypeB>
ArrayList<MyObjectTypeC>
I know i can do:
ArrayList<Object>
Then cast it to valid object type, but maybe there is faster and more performanced method to do it like:
ArrayList<MyObject>
and cast it to valid object type, will i lose additional object type data or cast will bring it back to my type?

If MyObjectTypeA and the rest inherit from MyObject then you can indeed create an ArrayList<MyObject> and store all of them and the cast them back to the correct object type.
However, note that this is an antipattern and usually a smell of bad code. You should only be doing this if you want to use any type of MyObject. If you want to use a specific type then you should create different Lists.
Regardless, if you are going to go through with bundling them all together in one list, at least before doing any casting you should check if the object you are casting is actually an instance of the type you are casting to like so:
if (object instanceof MyObjectTypeA){
MyObjectTypeA typeA = (MyObjectTypeA) object;
} else if (object instanceof MyObjectTypeB) {
// etc.
}
Note that the process of casting does not change the object itself. That's why the correct naming is type casting. You essentially declare than an instance is of a specific type. This essentially "enables" the usage of the specific type's methods and members whereas previously they were there but they were not accessible because the compiler didn't know about them (since he thought the type of the object did not contain such members but inside the program memory it actually did).
As an example, if you try cheat like so:
MyObjectTypeA typeA = new MyObjectTypeA();
MyObject object = (MyObject) typeA;
MyObjectTypeB typeB = (MyObjectTypeB) object;
This will actually compile since the compiler knows that object can be of type MyObjectTypeB but it will warn you that you are doing an unchecked casting (not checking with instanceof like I showed earlier). That specific scenario, when reaching line 3 will throw a ClassCastException since the interpreter will attempt to cast object to MyObjectTypeB but will fail since object is of type MyObjectTypeB.

You can declare an arraylist of type base class and add to it objects of the inherited types.
ArrayList<BaseClass>

You need to clearly define your objects.
For example, if you have a Class A, and classes B and C inherit from A, then yes do the following:
ArrayList<A> temp= new ArrayList<A>;
Here you will be able to call the methods you would want using polymorphism.
You should also be aware of type-safety and type-casting. The object class is too generic.

Why not use a HashMap and store the Object as the value and the Key as the type?
HashMap<Type, Object> typeObjectMap = new HashMap<Type, Object>();

Related

How to understand this java extend syntax with angular bracket and letter I [duplicate]

I am currently studying Java and have recently been stumped by angle brackets(<>). What exactly do they mean?
public class Pool<T>{
public interface PoolFactory<T>{
public T createObject();
}
this.freeObjects = new ArrayList<T>(maxsize)
}
What does the <T> mean? Does it means that I can create an object of type T?
<T> is a generic and can usually be read as "of type T". It depends on the type to the left of the <> what it actually means.
I don't know what a Pool or PoolFactory is, but you also mention ArrayList<T>, which is a standard Java class, so I'll talk to that.
Usually, you won't see "T" in there, you'll see another type. So if you see ArrayList<Integer> for example, that means "An ArrayList of Integers." Many classes use generics to constrain the type of the elements in a container, for example. Another example is HashMap<String, Integer>, which means "a map with String keys and Integer values."
Your Pool example is a bit different, because there you are defining a class. So in that case, you are creating a class that somebody else could instantiate with a particular type in place of T. For example, I could create an object of type Pool<String> using your class definition. That would mean two things:
My Pool<String> would have an interface PoolFactory<String> with a createObject method that returns Strings.
Internally, the Pool<String> would contain an ArrayList of Strings.
This is great news, because at another time, I could come along and create a Pool<Integer> which would use the same code, but have Integer wherever you see T in the source.
It's really simple. It's a new feature introduced in J2SE 5. Specifying angular brackets after the class name means you are creating a temporary data type which can hold any type of data.
Example:
class A<T>{
T obj;
void add(T obj){
this.obj=obj;
}
T get(){
return obj;
}
}
public class generics {
static<E> void print(E[] elements){
for(E element:elements){
System.out.println(element);
}
}
public static void main(String[] args) {
A<String> obj=new A<String>();
A<Integer> obj1=new A<Integer>();
obj.add("hello");
obj1.add(6);
System.out.println(obj.get());
System.out.println(obj1.get());
Integer[] arr={1,3,5,7};
print(arr);
}
}
Instead of <T>, you can actually write anything and it will work the same way. Try writing <ABC> in place of <T>.
This is just for convenience:
<T> is referred to as any type
<E> as element type
<N> as number type
<V> as value
<K> as key
But you can name it anything you want, it doesn't really matter.
Moreover, Integer, String, Boolean etc are wrapper classes of Java which help in checking of types during compilation. For example, in the above code, obj is of type String, so you can't add any other type to it (try obj.add(1), it will cast an error). Similarly, obj1 is of the Integer type, you can't add any other type to it (try obj1.add("hello"), error will be there).
It is related to generics in java. If I mentioned ArrayList<String> that means I can add only String type object to that ArrayList.
The two major benefits of generics in Java are:
Reducing the number of casts in your program, thus reducing the number of potential bugs in your program.
Improving code clarity
is called a generic type. You can instantiate an object Pool like this:
PoolFactory<Integer> pool = new Pool<Integer>();
The generic parameter can only be a reference type. So you can't use primitive types like int or double or char or other primitive types.
<> is used to indicate generics in Java.
T is a type parameter in this example. And no: instantiating is one of the few things that you can't do with T.
Apart from the tutorial linked above Angelika Langers Generics FAQ is a great resource on the topic.
Generic classes are a type of class that takes in a data type as a parameter when it's created. This type parameter is specified using angle brackets and the type can change each time a new instance of the class is instantiated. For instance, let's create an ArrayList for Employee objects and another for Company objects
ArrayList<Employee> employees = new ArrayList<Employee>();
ArrayList<Company> companies = new ArrayList<Company>();
You'll notice that we're using the same ArrayList class to create both lists and we pass in the Employee or Company type using angle brackets. Having one generic class be able to handle multiple types of data cuts down on having a lot of classes that perform similar tasks.
Generics also help to cut down on bugs by giving everything a strong type which helps the compiler point out errors. By specifying a type for ArrayList, the compiler will throw an error if you try to add an Employee to the Company list or vice versa.

Find out if GSON's TypeToken contains a List?

I'm using GSON to parse json in Java. When I want to get an integer list from a json String, my code may look like this:
Type type = new TypeToken<List<Integer>>(){}.getType();
List<Integer> result = null;
try {
result = new Gson().fromJson(jsonStringGoesHere, type);
} catch (JsonSyntaxException e) {
e.printStackTrace();
}
If jsonStringGoesHere is an empty String or null, result is also null.
It is considered bad practice to have an Collection equal null though, so I would prefer to have an empty List instead of null for this case.
So basically this is what I want to do now: If result is null, I want to check if type is a List (or a subtype of List). If true, I'll make result an empty ArrayList. How do I check whether type contains a List or subtype of List though?
My attempt was checking if(type instanceof Collection) - but that returns false.
My next try was to take type.getTypeName() which returns the String java.util.List<java.lang.Integer>, and tried to create an object from that:
Class c = Class.forName(type.getTypeName());
Object o = c.newInstance();
if(o instanceof List){
System.out.println("it's working!");
}
But this throws java.lang.ClassNotFoundException: java.util.List<java.lang.Integer>.
Any ideas how to make this work?
My attempt was checking if(type instanceof Collection) - but that returns false.
This won't work because Type and Collection are not "mutually castable" and exist in different hierarchies.
My next try was to take type.getTypeName() which returns the String java.util.List<java.lang.Integer>
This won't work either. Class.forName returns an existing Class<?> instance by a fully qualified name (simply speaking, something that's represented by a .class file in CLASSPATH), but never -- a parameterized class (classes are not parameterizable but can be subclasses with parameterized superclasses -- this is what's under the hood of type tokens). Thus, Class.forName("java.util.List") makes sense, but Class.forName("java.util.List<String>") does not.
Note that Type is something that can represent a type, and TypeToken<T> serves this purpose. Just take a look at how it's declared -- and you'll understand it better. Even more, its subinterface ParameterizedType can hold type parameters, and this this can be generated either by TypeToken or constructed manually (as usual -- just take a look at the interface declaration). TypeTokens usually use anonymous base class parameterization to take the type parameters from, and that's why they are designed like that: well-done compile-time support + there are similar techniques in Google Guava, Jackson, Spring Framework (but it would be nice if Java could support something like java.util.List<Integer>.type to get a parameterized type instance). As of later Gson versions, you can even use TypeToken.getParameterized(...) that is simply a convenience method to create a parameterized type.
What you're looking for is, a "class-instanceof" or "a-subclass-of" (if it's fine to call it like that): Class.isAssignableFrom(...). This instance method checks if one class is the same or a subclass of a another class. Say,
SuperClass.class.isAssignableFrom(SubClass.class)
always returns true. So you only have to check like this:
final Type type = new TypeToken<List<Integer>>() {
}.getType();
final TypeToken<?> typeToken = TypeToken.get(type);
System.out.println(List.class.isAssignableFrom(typeToken.getRawType()));
Or even shorter:
final TypeToken<List<Integer>> typeToken = new TypeToken<List<Integer>>() {
};
System.out.println(List.class.isAssignableFrom(typeToken.getRawType()));
Both return true. Note that type tokens return Class<?> instances via getRawType(), but not getType() since the latter may represent not a class (say, what would Collection<String>.class.isAssignableFrom(List<Integer.class>) return?)
Also, you can extract type tokens and its types to static final fields since they are meant to be immutable values and should not change in runtime.
In Java Generic part of collection comes into play at compile time, and therefore it is not available at runtime and that is the reason you are getting that exception. So if you want to create class of Collection type using reflection then you have to remove the generic part.
Also List,Set and Map are interfaces they can not be instantiated directly. So in order to create an object you have to use one of their implementation, like ArrayList,LinkedList etc.

Java.lang.Class.cast doesn't return a casted object

I am trying to cast an object to its superclass using Java.lang.Class.cast but I get the same object. What can be the reason?
This is the code I'm running:
public static void parse(Object obj)
{
// parse all super classes
Class<?> clazz = obj.getClass().getSuperclass();
if (!clazz.equals(prevClass))
{
prevClass = clazz;
Object castedObj = clazz.cast(obj);
parse(castedObj);
}
fillObject(obj);
}
but when passing to parse an object of dynamic type B, where B extends A, castedObj is equal to obj.
But I want castedObj to be a new object of dynamic type A because the parse method relies on that fact (iterates on the fields of the dynamic type class).
I am trying to cast an object to its superclass using Java.lang.Class.cast but I get the same object.
That is exactly what is supposed to happen.
For reference types, a cast is simply a type check. For example:
A a = (A) b;
This says to check that b is-a A and the assign the reference so that we can refer to it as an A using a.
There is no object conversion going on. No creation of new instances. The value assigned to a is identical in every respect to the value in b.
The same also applies when you use reflection to do the typecasting.
Or to put it another way, the value returned by getClass() for a given object is always going to be the same ... no matter how you cast is.
It is not clear what you are trying to do in your code, but it we assume that fillObject is filling in fields that relate to a particular class, then you most likely need to pass the Class as an explicit parameter. The true class of obj is always going to be the object's actual class ... irrespective of any casting.

What does <T> (angle brackets) mean in Java?

I am currently studying Java and have recently been stumped by angle brackets(<>). What exactly do they mean?
public class Pool<T>{
public interface PoolFactory<T>{
public T createObject();
}
this.freeObjects = new ArrayList<T>(maxsize)
}
What does the <T> mean? Does it means that I can create an object of type T?
<T> is a generic and can usually be read as "of type T". It depends on the type to the left of the <> what it actually means.
I don't know what a Pool or PoolFactory is, but you also mention ArrayList<T>, which is a standard Java class, so I'll talk to that.
Usually, you won't see "T" in there, you'll see another type. So if you see ArrayList<Integer> for example, that means "An ArrayList of Integers." Many classes use generics to constrain the type of the elements in a container, for example. Another example is HashMap<String, Integer>, which means "a map with String keys and Integer values."
Your Pool example is a bit different, because there you are defining a class. So in that case, you are creating a class that somebody else could instantiate with a particular type in place of T. For example, I could create an object of type Pool<String> using your class definition. That would mean two things:
My Pool<String> would have an interface PoolFactory<String> with a createObject method that returns Strings.
Internally, the Pool<String> would contain an ArrayList of Strings.
This is great news, because at another time, I could come along and create a Pool<Integer> which would use the same code, but have Integer wherever you see T in the source.
It's really simple. It's a new feature introduced in J2SE 5. Specifying angular brackets after the class name means you are creating a temporary data type which can hold any type of data.
Example:
class A<T>{
T obj;
void add(T obj){
this.obj=obj;
}
T get(){
return obj;
}
}
public class generics {
static<E> void print(E[] elements){
for(E element:elements){
System.out.println(element);
}
}
public static void main(String[] args) {
A<String> obj=new A<String>();
A<Integer> obj1=new A<Integer>();
obj.add("hello");
obj1.add(6);
System.out.println(obj.get());
System.out.println(obj1.get());
Integer[] arr={1,3,5,7};
print(arr);
}
}
Instead of <T>, you can actually write anything and it will work the same way. Try writing <ABC> in place of <T>.
This is just for convenience:
<T> is referred to as any type
<E> as element type
<N> as number type
<V> as value
<K> as key
But you can name it anything you want, it doesn't really matter.
Moreover, Integer, String, Boolean etc are wrapper classes of Java which help in checking of types during compilation. For example, in the above code, obj is of type String, so you can't add any other type to it (try obj.add(1), it will cast an error). Similarly, obj1 is of the Integer type, you can't add any other type to it (try obj1.add("hello"), error will be there).
It is related to generics in java. If I mentioned ArrayList<String> that means I can add only String type object to that ArrayList.
The two major benefits of generics in Java are:
Reducing the number of casts in your program, thus reducing the number of potential bugs in your program.
Improving code clarity
is called a generic type. You can instantiate an object Pool like this:
PoolFactory<Integer> pool = new Pool<Integer>();
The generic parameter can only be a reference type. So you can't use primitive types like int or double or char or other primitive types.
<> is used to indicate generics in Java.
T is a type parameter in this example. And no: instantiating is one of the few things that you can't do with T.
Apart from the tutorial linked above Angelika Langers Generics FAQ is a great resource on the topic.
Generic classes are a type of class that takes in a data type as a parameter when it's created. This type parameter is specified using angle brackets and the type can change each time a new instance of the class is instantiated. For instance, let's create an ArrayList for Employee objects and another for Company objects
ArrayList<Employee> employees = new ArrayList<Employee>();
ArrayList<Company> companies = new ArrayList<Company>();
You'll notice that we're using the same ArrayList class to create both lists and we pass in the Employee or Company type using angle brackets. Having one generic class be able to handle multiple types of data cuts down on having a lot of classes that perform similar tasks.
Generics also help to cut down on bugs by giving everything a strong type which helps the compiler point out errors. By specifying a type for ArrayList, the compiler will throw an error if you try to add an Employee to the Company list or vice versa.

Casting to Unknown Type When Only Given Class Name as a String of That Type

I currently posses a List of Objects(Using Java 1.3), and let's say that I wanted to cast one of the Objects returned from list.get(i) to a type of which I only know the name of the Class as a String. Essentially, how do I
Object o = (classname)list.get(i); where className is a String variable of a className.
I thought that I could use ( Class.forName(className) )list.get(i), but I received a syntax error claiming that I forgot a semicolon.
Unfortunately, since I am using Java 1.3, I do not have access to the Class.cast(Object) method.
What is the name of the class used when casting to another type in Java 1.3? Is there some method that can give me the correct type I need with a String parameter of the class name?
what is the point of casting when all you do is assign the result to object?
All you would achieve is an exception if it did not implement the interface/extend or was the class or do nothing if it did.
For that a simple:
public static boolean IsInstance(object x, String className)
{
Class cls = Class.forName(className);
return cls.isInstance(x);
}
is sufficient (and cleaner)
If you were to the use reflection to get at the fields/methods of the class that's just fine
No, and you can't do this across most languages.
The reason is that the type to cast to has to be known at compile time, not at runtime (which is what you are trying to do).
If you think about it, it makes sense, because given that the variable could be any type name, how are you supposed to access the various members? You can't, not unless they are defined in a base type/interface that all instances implement, in which case you should just use that.
One scenario where the need for this arises is when enforcing type safety with a legacy system. For example, suppose you have a persistence system like Hibernate that provides a raw List of results from a "finder" method. Casting this raw List to a parameterized type will result in an unchecked warning, and if the List contains an object of the wrong type, a ClassCastException can be raised at an unspecified time in some distantly related code. It may be best to validate the contents of the list up front, using a mechanism like the OP suggests.
Here's the Java 1.3 version (without generics):
private static void checkType(Collection objs, String className)
throws ClassNotFoundException
{
Class clz = Class.forName(className);
Iterator i = objs.iterator();
while (i.hasNext()) {
Object obj = i.next();
if (!clz.isInstance(obj)) {
throw new ClassCastException();
}
}
}
In Java 5 and later, with generics, you can do something similar with the Class.cast() method to verify the contents of a collection, justifying the use of a SuppressWarnings annotation. In our review process, suppressing a warning without some "proof" that it is safe is filed as a bug.
I assume that you really wanted to write the following, instead of using Object on the left side. Since otherwise, it's really just about checking whether the object in the list is of the right type.
ClassName o = (classname)list.get(i);
Well, Java is statically typed. It's not possible that you give it a string and it gives you the corresponding static type, so that you can go without casting. Even with generics and Class<T>.cast, the cast destination type is not given by a string, but by the generic type-argument T, which is known at compile-time. You have to manually cast to the right type, or keep using the most common type (may be Object in your case).
If you do Class.forName(className), it gives you back an object of the type Class which contains information about the type at runtime, so that it allows you to do
Class.forName("my.stuff.MyClass").newInstance()
But the cast wants a type - not an object of some type. That is why the compiler told you there is something wrong with that code.
The static type of the reference returned by that is of Object. This is important: The dynamic type of an object that is referenced, and the static type of the reference that points to that object. The dynamic type of the object is what can be "controlled" by a string (by using Class.forName), but the static type of the reference that you have to do with at compile time, and that is (just to give an example) used to select functions that overload each other, can not be determined by a string.
The question was answered already, but I'd like to add that it seems a bit dubious that you should have a List in which you keep several different kinds of objects (in this case, any objects), yet you'd apparently like to invoke operations on them that are specific to each different type...
What's the point of this collection? Don't the instances you keep in it have anything in common - any common supertype that you could cast them into?

Categories

Resources