【问题标题】:Java type casting and variable type assignmentJava 类型转换和变量类型赋值
【发布时间】:2020-04-19 04:20:09
【问题描述】:

我知道标题很奇怪,我不知道还能写什么。我对java比较陌生,所以如果这是非常基本的东西,我深表歉意。我已经尽力通过代码来解释这一点。 这里的问题是 -

这样编译,

// WAY 1
Map<MyType, MyType> myMap = (Map) new MyMap();

这不是,

// WAY 2
Map<MyType, MyType> myMap2 = (Map<MyType, MyType>) new MyMap();

首先,为什么会有这样的行为。其次,方式 2 允许我在一行中编写我想要的代码,如方法 WhatIWant 中所写,而方式 1 不允许,再次如方法 WhatIWant 中所写。我可以在一行中编写该代码吗?如果是,如何。如果没有,为什么不呢。

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

// A class not created by me but in a library so i cannot use generic types as i cannot change stuff here
class MyMap extends LinkedHashMap<Object, Object> {
}

// has methods which i need for processing on myMap
class MyType {
    int myMethod() {
        return -1;
    }
}

class Scratch {
    public static void main(final String[] args) throws Exception {
        // WAY 1: 
        // compiles 
        // WARNING : Unchecked assignment: 'java.util.Map' to 'java.util.Map<MyType, MyType>'
        Map<MyType, MyType> myMap = (Map) new MyMap();

        // WAY 2:
        // does not compile 
        // ERROR: Inconvertible types; cannot case 'MyMap' to 'java.util.Map<MyType, MyType>'  
        Map<MyType, MyType> myMap2 = (Map<MyType, MyType>) new MyMap();
    }

    public static void WhatIWant() {
        // to be able to write code below in one line
        Map<MyType, MyType> myMap = (Map) new MyMap();
        myMap.entrySet().stream()
                .collect(Collectors.toMap(
                        entry -> entry.getKey().toString(),
                        entry -> entry.getValue().myMethod()
                ));

        // I thought it would work if i used WAY 2 like
        ((Map<MyType, MyType>) new MyMap()).entrySet().stream()
                .collect(Collectors.toMap(
                        entry -> entry.getKey().toString(),
                        entry -> entry.getValue().myMethod()
                ));
        // but as you saw above in WAY 2, it does not compile, how can i do this in one line
    }
}

【问题讨论】:

  • 只是一个问题....为什么要遍历空地图?如果您刚刚创建了新的 myMap 对象,它将没有任何元素
  • 为什么需要MyMap 类。为什么不直接使用LinkedHashMap&lt;MyType,MyType&gt;
  • @TheOni 这只是一个例子。这些不是实际的课程。有一个类是相似类型的库。 MyMap 和 MyType 是库类。
  • @Eran 有一个库,它有自己的类型,类似于 MyMap。它有一个方法,我使用它返回 MyMap。因此我只能决定如何使用它,而不是对现有库进行更改。

标签: java types casting


【解决方案1】:

如果您希望它在“一行”中(又名 1 语句,5 行),双重转换

((Map<MyType, MyType>) (Map) new MyMap()).entrySet().stream()
        .collect(Collectors.toMap(
                entry -> entry.getKey().toString(),
                entry -> entry.getValue().myMethod()
        ));

第一个转换使用 raw Map,因此 &lt;Object, Object&gt; 泛型类型参数被丢弃。这对于向后兼容是有效的,但会生成一个编译器警告,说明您不应该这样做:

Map 是原始类型。应该参数化对泛型类型Map&lt;K,V&gt; 的引用

然后第二个转换应用一组新的泛型类型参数。这对于向后兼容是有效的,但确实会生成一个编译器警告,说明您是靠自己的,因为不强制执行泛型参数类型:

类型安全:未经检查的从Map 转换为Map&lt;MyType,MyType&gt;

不能直接转换的原因是Map&lt;MyType,MyType&gt; 不是Map&lt;Object,Object&gt; 的子类型,即它在Java 类型系统中是不可能的转换。见Is List&lt;Dog&gt; a subclass of List&lt;Animal&gt;? Why are Java generics not implicitly polymorphic?

【讨论】:

    【解决方案2】:

    您需要对班级进行一些更改才能解决问题

    // instead Object use your own type
        class MyMap extends LinkedHashMap<MyType, MyType> {
        }
    

    现在您无需强制转换即可直接访问/执行方式 2:

    Map<MyType, MyType> myMap2 = new MyMap();
    

    这里也是:

    new MyMap().entrySet().stream()
                    .collect(Collectors.toMap(
                            entry -> entry.getKey().toString(),
                            entry -> entry.getValue().myMethod()
                    ));
    

    【讨论】:

    • 正如我在我的代码中所写的那样。 MyMap 和 MyType 是库类,我无法触摸它们。我所能做的就是决定如何使用它们。我无法对它们进行任何更改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-03
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    相关资源
    最近更新 更多