例如,假设你有两个类:
public class TestA {}
public class TestB extends TestA{}
我有一个返回List<TestB>的方法,我想将该列表中的所有对象强制转换为TestB,以便最终得到List<TestB>。
例如,假设你有两个类:
public class TestA {}
public class TestB extends TestA{}
我有一个返回List<TestB>的方法,我想将该列表中的所有对象强制转换为TestB,以便最终得到List<TestB>。
当前回答
class MyClass {
String field;
MyClass(String field) {
this.field = field;
}
}
@Test
public void testTypeCast() {
List<Object> objectList = Arrays.asList(new MyClass("1"), new MyClass("2"));
Class<MyClass> clazz = MyClass.class;
List<MyClass> myClassList = objectList.stream()
.map(clazz::cast)
.collect(Collectors.toList());
assertEquals(objectList.size(), myClassList.size());
assertEquals(objectList, myClassList);
}
这个测试演示了如何将List<Object>转换为List<MyClass>。但是需要注意的是,objectList必须包含与MyClass相同类型的实例。当List<T>使用时,可以考虑这个例子。为此,在构造函数中获取字段Class<T> clazz,并使用它来代替MyClass.class。
更新
实际上,在强类型Java AFAIK中,你不能从超类型转换为子类型。但是可以引入超类型实现的接口。
interface ITest {
}
class TestA implements ITest {
}
class TestB extends TestA {
}
public class Main {
public static void main(String[] args) {
List<ITest> testAList = Arrays.asList(new TestA(), new TestA());
Class<ITest> clazz = ITest.class;
List<ITest> testBList = testAList.stream()
.map(clazz::cast)
.collect(Collectors.toList());
System.out.println(testBList.size());
System.out.println(testAList);
}
}
或者可以从子类型转换为超类型。是这样的:
class TestA {
}
class TestB extends TestA {
}
public class Main {
public static void main(String[] args) {
var a = new TestA();
var b = new TestB();
System.out.println(((TestA) b));
List<TestB> testBList = Arrays.asList(new TestB(), new TestB());
Class<TestA> clazz = TestA.class;
List<TestA> testAList = testBList.stream()
.map(clazz::cast)
.collect(Collectors.toList());
System.out.println(testAList.size());
System.out.println(testAList);
}
}
供参考,我最初的答案指出了与泛型一起使用它的可能性。事实上,我从Hibernate DAO代码中获取了它。
其他回答
泛型的强制转换是不可能的,但是如果你以另一种方式定义列表,则可以将TestB存储在其中:
List<? extends TestA> myList = new ArrayList<TestA>();
在使用列表中的对象时,仍然需要进行类型检查。
我必须用公司系统的方法来实现:
interface MyInterface{}
Class MyClass implements MyInterface{}
该方法接收一个接口列表,也就是说,我已经实例化了一个接口列表
private get(List<MyInterface> interface) {
List<MyClass> myClasses = interface.stream()
.filter(MyClass.class::isInstance)
.map(MyClass.class::cast)
.collect(Collectors.toList());
}
您可以在Eclipse Collections中使用selectInstances方法。这将涉及创建一个新的集合,但不会像使用强制转换的公认解决方案那样有效。
List<CharSequence> parent =
Arrays.asList("1","2","3", new StringBuffer("4"));
List<String> strings =
Lists.adapt(parent).selectInstancesOf(String.class);
Assert.assertEquals(Arrays.asList("1","2","3"), strings);
我在示例中加入StringBuffer是为了说明selectInstances不仅向下转换类型,而且还将过滤集合是否包含混合类型。
注意:我是Eclipse Collections的提交者。
简单地转换为List<TestB>就可以了;但它不起作用,因为您不能将一个参数的泛型类型强制转换为另一个参数。然而,你可以通过一个中间通配符类型进行强制转换,这是允许的(因为你可以强制转换到通配符类型,只是有一个未选中的警告):
List<TestB> variable = (List<TestB>)(List<?>) collectionOfListA;
简单的答案
你不能直接类型转换。
解决方案
public <T> List<T> getSubItemList(List<IAdapterImage> superList, Class<T> clazz) {
return superList.stream()
.map(item -> clazz.isInstance(item) ? clazz.cast(item) : null)
.collect(Collectors.toList());
}
使用
private final List<IAdapterImage> myList = new ArrayList<>();
List<SubType> subTypeList = getSubItemList(myList,SubType.class);
所以这是一个简单的工作,我用来转换我的列表与超级类型到列表与子类型。我们使用的是java 8中引入的流api,在我们的超列表上使用map,我们只是检查传递的参数是否是我们的超类型的实例,返回项目。最后,我们收集成一个新的列表。当然,我们需要把result放到一个新的列表中。