有没有办法避免在此分层Builder模式中进行未经检查的类转换?
public abstract class BaseBuilder <T, B extends BaseBuilder<T,B>> {
public B setB1(String b1) {
this.b1 = b1;
return (B) this; // can I make this unchecked cast go away?
}
abstract public T build();
String b1;
}
Run Code Online (Sandbox Code Playgroud)
不,答案不是:
return B.class.cast(this);
Run Code Online (Sandbox Code Playgroud)
是的,我知道我可以使用@SuppressWarnings
这是Java在多级层次结构中继承Fluent方法返回类型的简化版本.
给出以下代码:
public enum X {
;
static interface BaseFoo<T, S extends BaseFoo<T, S>> {
S foo();
}
static interface Foo<T> extends BaseFoo<T, Foo<T>> {
void foo1();
}
static interface BaseBar<T, S extends BaseBar<T, S>> extends BaseFoo<T, S> {
S bar();
}
static interface Bar<T> extends BaseBar<T, Bar<T>>, Foo<T> {
void bar1();
}
}
Run Code Online (Sandbox Code Playgroud)
运行javac X.java我收到错误消息:
X.java:15: error: BaseFoo cannot be inherited with different arguments: <T,X.Bar<T>> and <T,X.Foo<T>>
static interface Bar<T> extends BaseBar<T, Bar<T>>, Foo<T> { …Run Code Online (Sandbox Code Playgroud) 在工作中进行代码审查并遇到了我以前从未见过的模板类型的使用。乍一看,代码似乎不应该编译,因为定义似乎是递归的。我将其归结为最简单的可验证示例:
interface Bar<T>
interface Foo<T: Bar<T>> // Surely this is recursive?
Run Code Online (Sandbox Code Playgroud)
我对模板类型如何工作的理解是:
interface Foo<T>-一个Foo的T,没有任何限制
interface Foo<T : Bar>- a Fooof T,其中T被限制为 aBar
假设我上面说的是真的,那么这对我来说没有意义:
interface Bar<T>- a Barof T, 没有约束T
interface Foo<T: Bar<T>>- a Fooof T,其中T被限制为 aBar<T>
哦哦,如何T定义Bar<T>?。
我们知道T是 a Bar<T>,所以如果我们替换Tin Bar<T>,那么它就是 a Bar<Bar<T>>。
我们还没有解决T的Bar......为了便于讨论,让我们来代替 …
我正在尝试实现一个表示XML树的类,如下所示:
public class XML<T extends XML<T>> {
private final List<MarkupLanguage> nodeList = new ArrayList<>();
private final Map<String, String> attributeList = new HashMap<>();
public T attr(final String key, final String value) {
if (value != null) {
this.attributeList.put(key, value);
}
return (T) this;
}
public T appendTo(final T node) {
node.add(this);
return (T) this;
}
...
}
Run Code Online (Sandbox Code Playgroud)
我的问题是键入这些条款 - 我正在取消选中"for return(T)this";
当我尝试单独使用XML类时:
final XML url = new XML("url");
new XML("loc")
.add("http://goout.cz")
.appendTo(url);
Run Code Online (Sandbox Code Playgroud)
我正进入(状态:
Unchecked cast to call appendTo(T) as a member …Run Code Online (Sandbox Code Playgroud) 考虑班级:
class OnlyIntegerTypeAllowed<T> {
OnlyIntegerTypeAllowed(Class<T> clazz) {
System.out.println(clazz);
if (clazz != Integer.class)
throw new RuntimeException();
}
}
Run Code Online (Sandbox Code Playgroud)
它被设计为只接受Type Arguments Integer.我们if-throw在其构造函数中添加了一个检查.这是检查类型参数的一种非常常见的方法.
但是,可以通过以下方式绕过(黑客入侵,欺骗)此检查:
OnlyIntegerTypeAllowed<Integer> normalWay =
new OnlyIntegerTypeAllowed<Integer>(Integer.class);
OnlyIntegerTypeAllowed<String> hacking =
new OnlyIntegerTypeAllowed<String>((Class<String>) Class.forName(Integer.class.getName()));
Run Code Online (Sandbox Code Playgroud)
无论上述两行有没有编译错误和没有抛出异常!
OMG - 强制执行Type Argument的更好方法吗?
我有以下界面:
public interface ClusterPopulation
{
public double computeDistance(ClusterPopulation other);
}
Run Code Online (Sandbox Code Playgroud)
是否可以在接口本身中指定,ClusterPopulation的实现A只能将A实现作为computeDistance的参数?
我看到的唯一的approching解决方案如下,但我不喜欢它:
使用泛型重新定义界面:
public interface ClusterPopulation
{
public <T extends ClusterPopulation> double computeDistance(T other);
}
Run Code Online (Sandbox Code Playgroud)
在实现中,如果参数不是来自良好类型,则抛出IllegalArgumentException,如果类型正常,则执行一些强制转换... Meeeeh!
即使采用这种方法,最终用户也只是通过阅读文档/查看代码实现/试验和错误来了解约束...
更好的解决方案?
我有一个我们已实现的树的问题,这是一个示例:
public interface TreeNode {
TreeNode getParent();
void setParent(TreeNode parent);
List<TreeNode> getChildren();
void setChildren(List<TreeNode> children);
}
Run Code Online (Sandbox Code Playgroud)
所以,到现在为止这很容易,但是我们有一些Tree的变体,所以我们有一些这样的接口:
public interface TreeNodeWithX extends TreeNode {
String getX();
void setX(String x);
}
public interface TreeNodeWithY extends TreeNode {
Boolean getY();
void setY(Boolean y);
}
Run Code Online (Sandbox Code Playgroud)
因此,我需要一个TreeNodeWithX对象(是的,它的实现)从其getParent方法返回一个TreeNodeWithX对象(对于TreeNode接口中的其他方法也是如此).
来自TreeNodeWithY的相同行为,getParent()应返回TreeNodeWithY.
我尝试过一些泛型方法,例如:
public interface TreeNode<T extends TreeNode> {
T getParent();
void setParent(T parent);
List<T> getChildren();
void setChildren(List<T> children);
}
Run Code Online (Sandbox Code Playgroud)
但是,在实施方法的某些时候,我总是遇到麻烦.我的问题是,我是否使用我的通用界面正确的方式或我在这里做错了什么?
这种递归泛型引用并没有真正帮助我...