我有一个基本上看起来像这样的界面:
public interface ISetting<T> {
public T getDefault();
public T value();
public void set(T value);
public String getName();
public default String getValueName() {
Object obj = value();
if (obj instanceof Boolean) {
return (boolean)obj ? "Yes" : "No";
}
return obj.toString();
}
}
然后在另一堂课中,我列出了 ISetting<?>
private List<ISetting<?>> settings = Arrays.asList(
new ClassMode(),
new EndMode(),
new PlayerLives(),
new JoinMidGame(),
new ScoreboardDisplay(),
new LifePerKill(),
new ExplosiveBullets(),
new ReloadTime());
这一切都完美地工作!但是,我使用代码的平台不支持Java 8,因此我必须使用Java 7,这就是问题所在。
如果我将Maven目标设置为1.7,则在pom.xml中如下所示:
<configuration>
<source>1.8</source>
<target>1.7</target>
</configuration>
然后,代码可以完美编译,没有任何错误。但是,当我尝试运行代码时,它给了我这个错误:
java.lang.ClassFormatError:类net / uniqraft / murder / match / settings / ISetting中的方法getValueName包含非法的修饰符:0x1
我尝试使用Google进行搜索,但找不到我理解或适用于我的情况的任何内容。
所以,我想,我将把整个代码库变成Java 7:
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
我看到的第一个错误是:
仅在源级别1.8或更高级别上允许使用默认方法
令人难以置信的烦人,我不知道该如何绕过。我的许多代码都依赖于默认实现。我想我只需要使用抽象类?
但是我看到的更具问题性的错误是List<Setting<?>>
:
Type mismatch: cannot convert from List<ISetting<? extends Object&Comparable<?>&Serializable>> to List<ISetting<?>>
我不知道这意味着什么或如何解决。Eclipse提供的快速修复没有帮助。
如果您需要查看完整的非剥离式ISetting类或完整的stacktrace,我将它们放置在外部,因为它们的空间非常大:
我将答案分为两部分,第一部分与类型推断有关,第二部分与默认方法有关:
类型推断
在Java 7中,无论上下文如何,表达式的类型都是相同的。因此,当您这样做时:
Arrays.asList(new ClassMode(), new EndMode(), ...);
它不会创建List<ISetting<?>>
。您可以通过将settings
类型更改为来使其工作List<? extends ISetting<?>>
。也就是说,可以包含可以是元素ISetting<?>
或其任何子类型的元素的列表:
List<? extends ISetting<?>> settings = Arrays.asList(new ClassMode(), new EndMode(), ...);
在Java 8中,List<ISetting<?>>
由于poly表达式,将结果列表分配给作品。这意味着某些表达式的推导类型会受到目标类型的影响。因此,当您这样做时:
private List<ISetting<?>> settings = Arrays.asList(new ClassMode(), new EndMode(), ...);
编译器分析目标类型,并将类型参数隐式传递给Arrays.asList()
,这等效于:
private List<ISetting<?>> settings = Arrays.<ISetting<?>>asList(new ClassMode(), new EndMode(), ...);
会创建一个List<ISetting<?>>
并将其分配给settings
。如果您不想更改settings
类型,则以上形式在Java 7中也适用。
默认方法
Java 7没有默认方法。相反,您可以创建一个抽象的骨架实现与您的接口一起使用。接口将定义类型,而骨骼实现将提供默认功能。
首先,将default
界面中的方法转换为常规方法声明:
public interface ISetting<T> {
T getDefault();
T value();
void set(T value);
String getName();
// Former default methods:
String getValueName();
boolean isHidden();
boolean isDefault();
// etc.
}
然后创建一个抽象类来保存默认的实现:
public abstract class AbstractSetting<T> implements ISetting<T> {
@Override
public String getValueName() {
Object obj = value();
if (obj instanceof Boolean) {
return ((Boolean) obj) ? "Yes" : "No";
}
return obj.toString();
}
@Override
public boolean isHidden() {
return false;
}
// etc.
}
现在,使您的具体类实现该ISetting<T>
接口并扩展AbstractSetting<T>
该类。例如:
public class ConcreteSetting extends AbstractSetting<Boolean> implements ISetting<Boolean> {
// concrete implementation
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句