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: Method getValueName in class
net/uniqraft/murder/match/settings/ISetting has illegal modifiers: 0x1
我尝试Google,但找不到任何我理解或似乎适用于我的情况.
所以,我想,我只是将整个代码库变成Java 7:
<configuration> <source>1.7</source> <target>1.7</target> </configuration>
我看到的第一个错误是:
Default methods are allowed only at source level 1.8 or above
这是令人难以置信的烦人,我不知道如何绕过它.我的很多代码依赖于默认的实现.我想我只需要使用抽象类呢?
但是,我看到的更多的问题是在列表<设置<?>>我有:
Type mismatch: cannot convert from List<ISetting<? extends Object&Comparable<?>&Serializable>> to List<ISetting<?>>
我不知道这意味着什么或如何解决它. quickfix Eclipse提供没有任何帮助.
如果您需要查看完全不被删除的ISetting类或完整的堆栈跟踪,那么我将它们放在外部,因为它们相当空间:
解决方法
类型推断
在Java 7中,表达式的类型与上下文无关.所以当你做:
Arrays.asList(new ClassMode(),...);
它不会创建List< ISetting<?>>.您可以通过将设置类型更改为列表<?扩展ISetting<?>> ;.也就是说,可以容纳可以是ISetting<?>的元素的列表.或其任何子类型:
List<? extends ISetting<?>> settings = Arrays.asList(new ClassMode(),...);
在Java 8中,将得到的列表分配给List< ISetting<?>>工作原因是poly expressions.这意味着某些表达式的推导类型可能受到目标类型的影响.所以当你做:
private List<ISetting<?>> settings = Arrays.asList(new ClassMode(),...);
编译器分析目标类型,并将类型参数隐含地传递给Arrays.asList(),这相当于执行:
private List<ISetting<?>> settings = Arrays.<ISetting<?>>asList(new ClassMode(),...);
其创建列表< ISetting<?>>并将其分配给设置.如果您不想更改设置类型,上述表单也适用于Java 7.
默认方法
Java 7没有默认方法.相反,您可以创建一个抽象的骨架实现与您的界面一起.接口将定义类型,骨架实现将提供默认功能.
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 }