-1

I am using two class

Class TestClassOne{
//Some methods
//Some methods
//Some methods
}

Class TestClassTwo extends TestClassOne{ 
//Some Variable
//Some Variable
//Some Variable
}

Now I am having TestClassOne object and can cast to TestClassTwo.

TestClassOne classOne = new TestClassOne();
TestClassTwo classTwo = (TestClassTwo)classOne;

Can I do this same for ArrayList? For example

ArrayList<TestClassOne> testList1 = new ArrayList<>();
ArrayList<TestClassTwo> testList2 = (ArrayList<TestClassTwo>) testList1;

But I am getting error that can not cast. Is there any other way to cast the ArrayList?

4 Answers4

2

Generic types can't be converted to each other like that. T<A> cannot be casted to T<B> even though B inherits from A.

In this particular case, what you could do is cast each individual element in the array list, and use these to create a new array list.

ArrayList<TestClassTwo> testList2 = testList1.stream().map(x -> (TestClassTwo)x)
                                             .collect(Collectors.toCollection(ArrayList::new))

Obviously, this will only work when the objects stored in the array list are all actually instances of TestClassTwo.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
1

Simple casting TestClassOne-> TestClassTwo will not work, unless your testList1 collection holds instances of TestClassTwo, and only them.

Casting that you want to achieve is impossible, because even though TestClassTwo extends TestClassOne, there is no gurantee, that class TestClassTwo would have a suficient constructor. TestClassTwo may have additional variables, that JVM would not know what to do with. So as you can see this would be problematic even for humans.

========================================================================== Casting in other way is possible. Because TestClassTwo will have same methods as TestClassOne, because it extends it.

========================================================================== If you want to hold elements of both TestClassOne and TestClassTwo in same collction, then you can use generic wildcards:

 List<? extends TestClassOne> testList1 = new ArrayList<>();

But you will have to check if given element is of type TestClassTwo, before casting.

TestClassOne one = testLis.get(1);
if(one instanceOf TestClassTwo.class) {
   (TestClassTwo) one; // handle me
}
   one; // can't be casted, but can be adapted

==========================================================================

Other solution would be to use an adapter constructor in TestClassTwo. It will accept TestClassOne as an argument (and optionaly insert additional parameters, if needed). The creation of TestClassTwo objects should be managed by you.

class TestClassTwo extends TestClassOne{ 

     TestClassTwo(TestClassOne in) {...}
}

Then you can use simply adapt:

List<TestClassOne> testList1 = new ArrayList<>();//add some arguments
List<TestClassTwo> testList2 = testList1.stream().map(TestClassTwo::new).collect(toList());
Beri
  • 11,470
  • 4
  • 35
  • 57
0

You can use generic class

class TestClassOne<T>
{

}
class TestClassTwo
{
}

Casting like this

List<TestClassOne<TestClassTwo>> list = new List<TestClassOne<TestClassTwo>>();
farukcolak
  • 19
  • 4
0

You can't. Inheritance with Type parameters are not supported.

Instead create a static helper method, which will iterate over one of the list, and cast each individual element, and return the new list. e.g.

    public static convert(ArrayList<ClassOne>) {
        ArrayList<ClassTwo> b = new ArrayList<ClassTwo>(); 
        forEach(classOne)  {
            b.add((ClassTwo)classOne);
        }
        return b;
    }
Shariq
  • 513
  • 4
  • 14