【问题标题】:How to promise type safety to the compiler in Java如何在 Java 中向编译器承诺类型安全
【发布时间】:2022-01-17 08:01:42
【问题描述】:

我如何向编译器承诺我所做的是类型安全的?

我有一个可以包含一些信息的“容器”类。我将所述类扩展为我将称为EContainer (E 表示扩展)的内容,并定义它可以包含一些特定信息,例如intstring。现在,我希望能够列出EContainers 并按intstring 对其进行排序,我的解决方案是创建一个ContainerList<T> 类,其中T 是您的排序依据,并且你传入一个 lambda 来充当 EContainer 的适配器以提取 T

到目前为止一切都很好,但是现在说我想以某种方式将列表划分为组,所以如果假设的 EContainer 的整数范围从 0 到 100,我想说“group @987654332 @s like this: 0-20, 21-50, 51-100".

我最初的猜测是,我会在EContainer 中添加一个我将称为getDelimiter 的函数,该函数将能够返回它所在的“组”,使用定义分隔符的受保护的预定义枚举,然而,这是我遇到问题的地方 - 我返回一个组的方式是拥有一个共享值 T,多个 EContainers 在运行 getDelimiter 后将返回,所以我会根据它进行分组,但是不幸的是,这意味着getDelimiter 将是一个多类型返回函数,我不知道我将如何准确地告诉编译器“是的,我知道我在做什么,而且我一定会回来@ 987654339@ 来自getDelimiter"

我可能可以通过在其中添加另一个 lambda 来解决这个问题,该 lambda 将定义调用 EContainer 以获取分隔符函数的函数,这应该是类型安全的,但我认为最终会在EContainer 中的一个不必要的样板,所以也许我不知道有更好的选择?不得不说,对于这个问题,我很难找到可以使用的关键词,所以我没有做太多的初步研究。

编辑:刚刚想到让getDelimiter 将所有内容都返回为Object,然后立即转换为T,听起来应该可行并且可以最大限度地减少样板。

【问题讨论】:

  • 我不确定我是否理解。为什么表示容器的类需要任何共享状态?当然,EContainer 的两个实例不需要访问任何公共内存。它们完全不同。
  • 我建议您发布您正在使用的代码,而不是试图描述它。
  • @shmosel 我刚刚发布了我自己的评论和一个工作代码。

标签: java generics types


【解决方案1】:
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Comparator;
    
    public class StackOverflowNonsense {
        public static abstract class Container{
            public String sharedFunc(){return "this is a shared function";}
        }
        public static class EContainer{
            public int _int; //id=0
            public float _float; //id=!0
            public EContainer(int _int,float _float){
                this._int=_int;
                this._float=_float;
            }
            protected enum Delimiters{
                INT(new ArrayList<Object>(Arrays.asList(0,21,51))),
                FLOAT(new ArrayList<Object>(Arrays.asList((float)0,(float)0.5,(float)1)));
                final ArrayList<Object> delim;
                Delimiters(ArrayList<Object> delim){
                    this.delim=delim;
                }
            }
            public Object getDelimiter(int id){
                if (id==0){
                    int pos=Collections.binarySearch(Delimiters.INT.delim, (Object)_int,Comparator.comparingInt(key->(int)key));
                    return (Object)Delimiters.INT.delim.get(pos<0?-2-pos:pos);
                }else{
                    int pos=Collections.binarySearch(Delimiters.FLOAT.delim, (Object)_float,Comparator.comparingDouble(key->(Float)key));
                    return (Object)Delimiters.FLOAT.delim.get(pos<0?-2-pos:pos);
                }
            }
            @Override
            public String toString(){
                return String.format("EContainer with (%d, %f)", _int,_float);
            }
        }
            public static void main(String[] args){
                ArrayList<EContainer> ContainerList=new ArrayList<>(
                Arrays.asList(new EContainer(0,(float)2.0),new EContainer(69,(float)0.69))
                );
                Collections.sort(ContainerList,Comparator.comparingInt(key->(int)key.getDelimiter(0)));
                System.out.println(ContainerList);
                Collections.sort(ContainerList,Comparator.comparingDouble(key->(Float)key.getDelimiter(1)));
                System.out.println(ContainerList);
            }
    }

这似乎提供了我想要的功能,但是我不确定这段代码是否破坏了一些神圣的脚本,所以也许有更好的解决方案?

【讨论】:

    【解决方案2】:

    我如何向编译器承诺我所做的是类型安全的?

    一般来说,@SuppressWarnings("unchecked") 就是这样做的。

    尚不清楚它是否适用于您的用例。 (向我们展示您的实际代码......如果您想要更具体的答案。)

    但是,仍然会有一个隐藏的运行时检查来检测您没有违反运行时类型安全性。 没有办法你可以关闭这些检查。


    刚刚想到让getDelimiter 将所有内容返回为Object,然后立即转换为T,听起来应该可以,并且可以最大限度地减少样板。

    嗯...您不能将静态类型为Object 的内容转换为T。根本问题是 T 的实际类型被删除了,所以运行时不知道要转换成什么类型​​。

    一种可能的解决方法是将T 的实际类型表示为Class 对象,并使用反射来进行类型检查/转换。实际上,当您需要进行类型检查(尽管类型擦除)时,这是一般的解决方法。不幸的是,这很麻烦,因为在某些时候您需要传递一个额外的显式 Class 对象作为参数才能使其工作。

    【讨论】:

      猜你喜欢
      • 2012-08-26
      • 2019-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-05
      • 2015-11-15
      相关资源
      最近更新 更多