如何在Java中提示两个类型参数实际上是相同的类型?

huangapple go评论79阅读模式
英文:

How to give hint in Java that two type parameters are actually the same type?

问题

<!-- language-all: lang-java -->

我正在使用AOSP的[`CaptureRequest`][1]及其相关的[`CaptureRequest.Builder`][2]尽管情况非常不同寻常但我需要将现有的`CaptureRequest`实例的设置键值复制到新的`CaptureRequest.Builder`<sup>1</sup>实例中

我想要运行的基本代码如下

            for(CaptureRequest.Key<?> key : request.getKeys()) {
                builder.set(key, request.get(key));
            }
 
...其中`CaptureRequest.Builder.set()`函数定义为`<T> void set(Key<T> key, T value)`,`CaptureRequest.get()`定义为`<T> T get(Key<T> key)`。
但这会导致编译器报错错误信息如下

    Source.java:2: error: method set in class Builder cannot be applied to given types;
                    builder.set(key, request.get(key));
                           ^
      required: Key<T>,T
      found: Key<CAP#1>,CAP#2
      reason: inferred type does not conform to lower bound(s)
        inferred: CAP#1
        lower bound(s): Object
      where T is a type-variable:
        T extends Object declared in method <T>set(Key<T>,T)
      where CAP#1,CAP#2 are fresh type-variables:
        CAP#1 extends Object from capture of ?
        CAP#2 extends Object from capture of ?

如果我正确解释了错误信息它试图表达的是无法将两个函数的`<T>`关联为相同的`T`。为了给它一个提示表明它是相同的`T`,我创建了一些辅助函数应该可以明确它是相同的`T`,因此我有了这个

    private static <T> T getKeyValue(CaptureRequest request, CaptureRequest.Key<T> key) {
        return (T)request.<T>get(key);
    }

    private static <T> void setKeyValue(CaptureRequest.Builder builder, CaptureRequest.Key<T> key) {
        builder.<T>set(key, (T)MyClass.<T>getKeyValue(key));
    }

    .....

            for(CaptureRequest.Key<?> key : request.getKeys()) {
                setKeyValue(builder, key);
            }

这无法使Java编译器满意它会输出与先前错误非常相似的错误

      Source.java:6: error: method getKeyValue in class MyClass cannot be applied to given types;
            builder.<T>set(key, (T)MyClass.<T>getKeyValue(key));
                                          ^
      required: CaptureRequest,Key<T#1>
      found: Key<T#2>
      reason: actual and formal argument lists differ in length
      where T#1,T#2 are type-variables:
        T#1 extends Object declared in method <T#1>getKeyValue(CaptureRequest,Key<T#1>)
        T#2 extends Object declared in method <T#2>setKeyValue(Builder,Key<T#2>)

如何以合理的方式执行这个[本应该简单的]键值复制
 
----------
<sup>1</sup> 是的我知道这很奇怪与通常的API使用有些不同因此不寻常”。背景是已构建的请求超出库的范围正在通过需要使用自己的阴影请求对请求进行处理大部分情况下模仿原始请求但稍作修改而且该库无法访问原始构建器以构建阴影同级请求是的这很奇怪超出了这个问题的范围这个问题实际上是关于Java的模板方法和明显的编译错误

  [1]: https://developer.android.com/reference/android/hardware/camera2/CaptureRequest
  [2]: https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.Builder
英文:

<!-- language-all: lang-java -->

I'm working with AOSP's CaptureRequest and its associated CaptureRequest.Builder classes, and have (albeit very unusual case of) a need to copy settings key-values from an existing instance of CaptureRequest to a new instance of CaptureRequest.Builder<sup>1</sup>.

The basic code here that I want to run is the following:

        for(CaptureRequest.Key&lt;?&gt; key : request.getKeys()) {
builder.set(key, request.get(key));
}

... where CaptureRequest.Builder.set() function is defined as &lt;T&gt; void set(Key&lt;T&gt; key, T value), and CaptureRequest.get() is defined as &lt;T&gt; T get(Key&lt;T&gt; key).
But that makes compiler barf with the following error:

Source.java:2: error: method set in class Builder cannot be applied to given types;
builder.set(key, request.get(key));
^
required: Key&lt;T&gt;,T
found: Key&lt;CAP#1&gt;,CAP#2
reason: inferred type does not conform to lower bound(s)
inferred: CAP#1
lower bound(s): Object
where T is a type-variable:
T extends Object declared in method &lt;T&gt;set(Key&lt;T&gt;,T)
where CAP#1,CAP#2 are fresh type-variables:
CAP#1 extends Object from capture of ?
CAP#2 extends Object from capture of ?

If I'm interpreting the error correctly, it's trying to say that it cannot relate &lt;T&gt;s of two functions as being the same one T. So to give it a hint that it's the same T, I created some helper functions that should make it obvious that it's the same T, and so I have this:

private static &lt;T&gt; T getKeyValue(CaptureRequest request, CaptureRequest.Key&lt;T&gt; key) {
return (T)request.&lt;T&gt;get(key);
}
private static &lt;T&gt; void setKeyValue(CaptureRequest.Builder builder, CaptureRequest.Key&lt;T&gt; key) {
builder.&lt;T&gt;set(key, (T)MyClass.&lt;T&gt;getKeyValue(key));
}
.....
for(CaptureRequest.Key&lt;?&gt; key : request.getKeys()) {
setKeyValue(builder, key);
}

This fails to pacify the Java compiler and it spits out very similar error to the previous one:

  Source.java:6: error: method getKeyValue in class MyClass cannot be applied to given types;
builder.&lt;T&gt;set(key, (T)MyClass.&lt;T&gt;getKeyValue(key));
^
required: CaptureRequest,Key&lt;T#1&gt;
found: Key&lt;T#2&gt;
reason: actual and formal argument lists differ in length
where T#1,T#2 are type-variables:
T#1 extends Object declared in method &lt;T#1&gt;getKeyValue(CaptureRequest,Key&lt;T#1&gt;)
T#2 extends Object declared in method &lt;T#2&gt;setKeyValue(Builder,Key&lt;T#2&gt;)

How can I perform this [what should be simple] copy of key-values in a sane way?


<sup>1</sup> Yes, I know that's weird and a bit backwards from typical use of API, hence "unusual". Context is that already built request (beyond library's scope) is percolating through a library that needs to shadow request with its own, mostly mimicking the original, but slightly amended, and said library doesn't have access to original builder to build the shadow sibling request. Yes, it's weird and is beyond the scope of this question. This question is really about Java's template methods and apparent compilation error.

答案1

得分: 1

为什么不只是:

builder.set((CaptureRequest.Key&lt;Object&gt;)key, request.get(key));

我很确定它应该可以工作。

英文:

Why not just:

builder.set((CaptureRequest.Key&lt;Object&gt;)key, request.get(key));

Pretty sure it should work.

huangapple
  • 本文由 发表于 2020年9月19日 07:53:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/63964038.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定