Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中具有有限作用域的类型变量_Java_Generics - Fatal编程技术网

Java中具有有限作用域的类型变量

Java中具有有限作用域的类型变量,java,generics,Java,Generics,我想知道是否有可能在Java中的方法范围内引入类型变量。也就是说,在方法体中限制它们的范围 然而,与其试图抽象地描述问题,不如让我用我的具体问题来说明。我有几门课看起来有点像这样: public class Settings { public static abstract class Setting<T> { public T value; public abstract T fallbackvalue(); } priva

我想知道是否有可能在Java中的方法范围内引入类型变量。也就是说,在方法体中限制它们的范围

然而,与其试图抽象地描述问题,不如让我用我的具体问题来说明。我有几门课看起来有点像这样:

public class Settings {
    public static abstract class Setting<T> {
        public T value;
        public abstract T fallbackvalue();
    }

    private final List<Setting<?>> settings;
}
public void reset() {
    for(Setting<?> setting : settings)
        setting.value = setting.fallbackvalue();
}
private static <T> void reset1(Setting<T> s) {
    s.value = setting.fallbackvalue();
}

public void reset() {
    for(Setting<?> setting : settings)
        reset1(setting);
}
public void reset() {
    for(Setting<?> setting : settings) {
        <T> {
            Setting<T> foo = setting;
            foo.value = foo.fallbackvalue();
        }
    }
}
然而,经过再三思考,很明显为什么这不起作用;setting.value的
捕获与setting.fallbackvalue()的捕获不同。因此,我需要一些方法来统一捕获。可以这样解决:

public class Settings {
    public static abstract class Setting<T> {
        public T value;
        public abstract T fallbackvalue();
    }

    private final List<Setting<?>> settings;
}
public void reset() {
    for(Setting<?> setting : settings)
        setting.value = setting.fallbackvalue();
}
private static <T> void reset1(Setting<T> s) {
    s.value = setting.fallbackvalue();
}

public void reset() {
    for(Setting<?> setting : settings)
        reset1(setting);
}
public void reset() {
    for(Setting<?> setting : settings) {
        <T> {
            Setting<T> foo = setting;
            foo.value = foo.fallbackvalue();
        }
    }
}

这不是世界上最漂亮的东西,但至少在我看来,它远没有上面的变体那么紧张。唉,这是不可能的;但是什么是可能的呢?

如果不更改代码的其他方面,就无法实现您的要求。但是(为了解决您的特定问题),您可以在内部
设置
类中编写
重置
方法:

public void reset() {
    value = fallbackvalue();
}
然后您的循环(在
设置
类的
重置
方法中)将是:

for (Setting<?> setting : settings)
    setting.reset();
for(设置:设置)
seting.reset();

虽然通配符捕获引入了新的类型变量,但它们只对编译器可用;程序员无法直接访问它们


目前,只有类/方法可以引入类型变量。因此,将带有通配符的表达式类型转换为不带通配符的类型的唯一方法是通过一个方法传递表达式(或者通过一个具有菱形推理的构造函数
new Foo(setting)
,这基本上是相同的机制)

您的
reset1
方法是普遍接受的。它被称为“捕获助手”,是泛型中经常引用的模式。它通常出现在如下情况下:

public void swap(List<?> list, int i, int j) { // swap elements i and j of the list
    // how to write?
}
public void交换(List List,int i,int j){//交换列表中的元素i和j
//如何写作?
}
在这种情况下,您需要从参数化类型中获取一些内容,并将这些内容放回该类型中。通配符就是不允许你这么做。这和你的情况一样,因为你也在把东西拿出来放进去。我们知道类型必须相同,但通配符太弱,无法强制执行。只有显式类型变量才允许执行此操作:

public <T> void swap(List<T> list, int i, int j) {
    T tmp = list.get(i);
    list.set(i, list.get(j));
    list.set(j, tmp);
}
公共无效交换(列表、int i、int j){
T tmp=list.get(i);
list.set(i,list.get(j));
列表集(j,tmp);
}
但是,我们不希望此无关的
仅用于参数列表中的一个位置。对于外界来说,
swap(List-List,inti,intj)
应该可以很好地工作。我们需要使用这个
类型参数,这是一个实现细节,没有人需要知道。为了隐藏它,我们用接受通配符的函数包装泛型函数:

private <T> void swap_private(List<T> list, int i, int j) { ... }
public void swap(List<?> list, int i, int j) {
    swap_private(list, i, j);
}
private void swap_private(List List,int i,int j){…}
公共无效交换(列表、int i、int j){
交换私有(列表,i,j);
}
这看起来确实是浪费,但事实就是这样


考虑到您的情况与此情况类似,而且捕获助手是此情况下的标准解决方案,我可以自信地告诉您,没有更好的方法可以做到这一点。

当然,但这与
reset1
函数基本相同,除了
Settings.reset
的内部实现细节之外,它没有任何用途。不管怎样,我对类型捕获管理的更一般的问题感兴趣。@Dolda2000是的,基本上是
reset1
,但是在一个更合乎逻辑的地方。最终,我认为这是最好/最干净/最容易管理/最可读的解决方案。此外,我不确定你的问题是否可以通过其他方式解决(但我可能错了——这以前发生过)。如果我想到一种不太复杂的方法(即,不要求对代码的其他方面进行更改),我一定会更新我的答案。当然,但问题不是如何在本地OOP中正确建模示例概念,而是关于类型捕获管理恐怕我不得不承认你是对的。更多的谷歌搜索似乎确实普遍建议使用“
reset1
”方法作为解决问题的通用方法。那是。。。太糟糕了。