Java 将CharBuffer和StringBuilder转换为superinterface
StringBuilder和CharBuffer都实现CharSequence和Appendable接口。 在声明超级接口时Java 将CharBuffer和StringBuilder转换为superinterface,java,stringbuilder,charsequence,Java,Stringbuilder,Charsequence,StringBuilder和CharBuffer都实现CharSequence和Appendable接口。 在声明超级接口时 public interface IAppendableCharSequence extends CharSequence, Appendable{} 然后我可以将CharBuffer强制转换为IAppendableCharSequence,但不能转换为StringBuilder: private IAppendableCharSequence m_buffer;
public interface IAppendableCharSequence extends CharSequence, Appendable{}
然后我可以将CharBuffer强制转换为IAppendableCharSequence,但不能转换为StringBuilder:
private IAppendableCharSequence m_buffer;
// ...
m_buffer = (IAppendableCharSequence) CharBuffer.allocate(512); // ok
m_buffer = (IAppendableCharSequence) new StringBuilder(512); // Cannot cast from StringBuilder to IAppendableCharSequence
为什么呢?谢谢 这两种方法在运行时都不起作用,但编译器允许其中一种而不允许另一种的原因是
StringBuilder
是final
而CharBuffer
不是
编译器肯定知道,作为StringBuilder的实例的任何东西都不能是IAppendableCharSequence
的有效实现,因为StringBuilder
本身不实现该接口,并且作为final
它不能有子类。因此,在任何情况下,强制转换都不可能是合法的,编译器会拒绝它
在CharBuffer
的情况下,编译器没有这种保证,因为您可能会创建CharBuffer
的自定义子类,该子类实现IAppendableCharSequence
编译器允许哪些类型转换而哪些不允许的规则在Java语言规范中,在本例中(缩小引用转换),其中包括允许转换的规则
从任何类类型C
到任何非参数化接口类型K
,前提是C
不是final
且不实现K
也就是说,如果类不是最终类,则从任何类类型转换到该类未实现的任何接口类型都是有效的。这两种转换在运行时都不会实际工作,但编译器允许其中一种而不允许另一种的原因是StringBuilder
是final
而CharBuffer
不是
编译器肯定知道,作为StringBuilder的实例的任何东西都不能是IAppendableCharSequence
的有效实现,因为StringBuilder
本身不实现该接口,并且作为final
它不能有子类。因此,在任何情况下,强制转换都不可能是合法的,编译器会拒绝它
在CharBuffer
的情况下,编译器没有这种保证,因为您可能会创建CharBuffer
的自定义子类,该子类实现IAppendableCharSequence
编译器允许哪些类型转换而哪些不允许的规则在Java语言规范中,在本例中(缩小引用转换),其中包括允许转换的规则
从任何类类型C
到任何非参数化接口类型K
,前提是C
不是final
且不实现K
即,如果该类不是最终类,则从任何类类型转换为该类未实现的任何接口类型是有效的。@Ian Roberts是正确的
谜题的另一部分是Java类型系统将IAppendableCharSequence
视为不仅仅是CharSequence
和appendeable
。实际上,它本身就是一个类型,可以有相关的语义。。。这样,既是字符序列
又是可追加的
的“任何旧类”都不符合条件
这意味着下面的CharBuffer
或StringBuilder
是一个IAppendableCharSequence
,即使它们都实现了CharSequence
和appendeable
接口
java接口更多的是C或C++别名,即使它们只扩展其他接口…
@阿兰·罗伯茨是正确的。< /P>
谜题的另一部分是Java类型系统将IAppendableCharSequence
视为不仅仅是CharSequence
和appendeable
。实际上,它本身就是一个类型,可以有相关的语义。。。这样,既是字符序列
又是可追加的
的“任何旧类”都不符合条件
这意味着下面的CharBuffer
或StringBuilder
是一个IAppendableCharSequence
,即使它们都实现了CharSequence
和appendeable
接口
java接口更多的是C或C++别名,即使它们只扩展其他接口…
我可以将CharBuffer强制转换为IAppendableCharSequence
事实上你不能。只能将类的实例强制转换为该类有意实现的类型。CharBuffer实现Appendable和CharSequence并不意味着它实现了IAppendableCharSequence接口
编译器允许强制转换,因为它无法判断CharBuffer.allocate(512)
将返回什么。据编译器所知,它可以返回CharBuffer的子类,该子类确实显式实现了IAppendableCharSequence。但是,如果对象没有真正实现该接口,则cast将在运行时抛出ClassCastException
然而,newstringbuilder(512)
保证新对象是一个StringBuilder,而不是它的子类,因此编译器可以在编译时看到强制转换不起作用
解决问题的一个方法是制作一个实现接口的通用包装器:
public static <T extends CharSequence & Appendable> IAppendableCharSequence wrap(T t) {
if (t == null) throw new NullPointerException();
final CharSequence csq = t;
final Appendable a = t;
return new IAppendableCharSequence() {
@Override
public int length() {
return csq.length();
}
@Override
public char charAt(int index) {
return csq.charAt(index);
}
@Override
public CharSequence subSequence(int start, int end) {
return csq.subSequence(start, end);
}
@Override
public Appendable append(CharSequence s) throws IOException {
a.append(s);
return this;
}
@Override
public Appendable append(CharSequence s, int start, int end) throws IOException {
a.append(s, start, end);
return this;
}
@Override
public Appendable append(char c) throws IOException {
a.append(c);
return this;
}
};
}
您还可以使用实现CharSequence和Appendable的任何其他方法调用它
我可以将CharBuffer强制转换为IAppendableCharSequence
事实上你不能。只能将类的实例强制转换为该类有意实现的类型。CharBuffer实现Appendable和CharSequence并不意味着它实现了IAppendableCharSequence接口
编译器允许强制转换,因为它无法判断CharBuffer.allocate将返回什么
m_buffer = wrap(CharBuffer.allocate(512));
m_buffer = wrap(new StringBuilder(512));