美文网首页
Effective Java - 不要使用原生态类型

Effective Java - 不要使用原生态类型

作者: DZQANN | 来源:发表于2022-06-12 22:14 被阅读0次

泛型使用注意事项

  1. 这一条的核心宗旨就是要用List<>,不要用List

  2. ListList<Object>也是有区别的,List逃避了泛型检查,而List<Object>则明确地告诉编译器,它能够有任意类型的对象。

  3. 如果要使用泛型,但不确定或者不关心实际的类型参数,可以使用一个问号(无限制的通配符类型)代替。比如Set<?>

  4. 使用原生态类型的场景:

    • 传递class,比如List.class

    • instanceof,比如o instanceof Set。这个时候强转也只能强转成Set<?>

      if (o instanceof Set) {
        Set<?> s = (Set<?>) o;
      }
      

思考

  1. 使用反应一定要加上类型限制,而且限制的越具体越好(比如extendssuper)。

  2. 已有项目里有可能会出现比较多的原生态类型,主要原因猜测有几种:

    • 写代码的时候还没有泛型,或者Java版本还没到
    • 从网上直接抄的代码
    • 使用了反射,json转换的时候需要转成Map,只能传Map.class
  3. 如果有json转泛型类的需求,可以使用TypeReference,它在不同的Json库中都有定义。它的基本原理就是用反射方法拿到了泛型。

    • fastjson的TypeReference的构造方法:

      protected TypeReference() {
        Type superClass = this.getClass().getGenericSuperclass();
        Type type = ((ParameterizedType)superClass).getActualTypeArguments()[0];
        Type cachedType = (Type)classTypeCache.get(type);
        if (cachedType == null) {
          classTypeCache.putIfAbsent(type, type);
          cachedType = (Type)classTypeCache.get(type);
        }
      
        this.type = cachedType;
      }
      
    • TypeReference的使用:

      首先定义好实体类:

      public class Father {
          private String name;
      
          private List<Father> selves = new ArrayList<>();
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public List<Father> getSelves() {
              return selves;
          }
      
          public void setSelves(List<Father> selves) {
              this.selves = selves;
          }
      
          @Override
          public String toString() {
              return "Father{" +
                      "name='" + name + '\'' +
                      ", selves=" + selves +
                      '}';
          }
      }
      

      Json:

      [
        {
          "name": "name1",
          "selves": [
            {
              "name": "name2"
            },
            {
              "name": "name3",
              "selves": [
                {
                  "name": "name4"
                }
              ]
            }
          ]
        }]
      

      使用TypeReference:

      List<Father> objects = JSON.parseObject("[\n" +
                      "  {\n" +
                      "    \"name\": \"name1\",\n" +
                      "    \"selves\": [\n" +
                      "      {\n" +
                      "        \"name\": \"name2\"\n" +
                      "      },\n" +
                      "      {\n" +
                      "        \"name\": \"name3\",\n" +
                      "        \"selves\": [\n" +
                      "          {\n" +
                      "            \"name\": \"name4\"\n" +
                      "          }\n" +
                      "        ]\n" +
                      "      }\n" +
                      "    ]\n" +
                      "  }]", new TypeReference<>() {
              });
              System.out.println(objects);
      

      运行结果:

      image.png
  1. 对于instanceof的情况,没有想到有可能会instanceof泛型类的情况,按道理来说也是可以通过object.getClass().getGenericSuperclass()拿到具体的泛型类的

  2. 泛型还有一个比较有意思的地方,不知道原因。下面两个代码,第一个为什么没有报错?

    • image.png
    • image.png

相关文章

网友评论

      本文标题:Effective Java - 不要使用原生态类型

      本文链接:https://www.haomeiwen.com/subject/fmramrtx.html