Java 类,该类使用返回泛型接口的工厂<;T>;解析T的列表,但不只是T
我有以下设置。我有一个由Java 类,该类使用返回泛型接口的工厂<;T>;解析T的列表,但不只是T,java,generics,interface,Java,Generics,Interface,我有以下设置。我有一个由StringFetcher实现的AbstractFetcher。然后我有一个工厂,它根据输入返回AbstractFetchers。。这里,OneClass正在使用AbstractFactoryFetcher。在方法doSomething中,我得到了第二行的编译器错误,但不是第一行!换句话说,fetchMany()编译得很好!发生这种情况的原因是什么?即使使用通用方法提示,如何更改签名,从而不需要强制转换?我的最终目标是使OneClass不必知道任何有关returnt的具体
StringFetcher
实现的AbstractFetcher
。然后我有一个工厂,它根据输入返回AbstractFetcher
s。。这里,OneClass
正在使用AbstractFactoryFetcher
。在方法doSomething
中,我得到了第二行的编译器错误,但不是第一行!换句话说,fetchMany()
编译得很好!发生这种情况的原因是什么?即使使用通用方法提示,如何更改签名,从而不需要强制转换?我的最终目标是使OneClass不必知道任何有关returnt的具体获取程序的信息,这样即使在FetcherFactory上有更改,也可以单独部署/编译它
public interface AbstractFetcher<T> {
T fetchOne();
List<T> fetchMany();
}
public class StringFetcher implements AbstractFetcher<String> {
@Override
public String fetchOne() {
return "a string"
}
@Override
public List<String> fetchMany() {
List<String> list = new ArrayList<>();
list.add("String 1");
list.add("String 2");
return list;
}
}
public interface AbstractFactoryFetcher {
public AbstractFactoryFetcher make(String type);
}
public class FetcherFactory implements AbstractFactoryFetcher {
public AbstractFetcher make(String type) {
if (type.equals("String")) {
return new StringFetcher();
}
else {
return null;
}
}
}
public class OneClass {
FetcherFactory factory;
public OneClass(FetcherFactory factory) {
this.factory = factory;
}
public void doSomething() {
List<String> list = factory.make("String").fetchMany();
String one = factory.make("String").fetchOne(); //compiler error Required: String, Found: Object
}
}
公共接口抽象获取程序{
T fetchOne();
List fetchMany();
}
公共类StringFetcher实现AbstractFetcher{
@凌驾
公共字符串fetchOne(){
返回“字符串”
}
@凌驾
公共列表fetchMany(){
列表=新的ArrayList();
列表。添加(“字符串1”);
列表。添加(“字符串2”);
退货清单;
}
}
公共接口AbstractFactoryFetcher{
public AbstractFactoryFetcher make(字符串类型);
}
公共类FetcherFactory实现AbstractFactoryFetcher{
公共抽象获取程序生成(字符串类型){
if(type.equals(“字符串”)){
返回新的StringFetcher();
}
否则{
返回null;
}
}
}
公共一类{
菲克特工厂;
公共OneClass(FetcherFactory工厂){
这个工厂=工厂;
}
公共无效剂量测定法(){
List List=factory.make(“字符串”).fetchMany();
String one=factory.make(“String”).fetchOne();//需要编译器错误:String,找到:Object
}
}
谢谢 您在
doSomething
中将AbstractFetcher
用作原始类型,这意味着使用了对其方法的擦除:
Object fetchOne();
List fetchMany();
而列表
可以转换为列表
(带有未选中的警告)。对象无法转换为字符串
最好是强类型工厂:
public AbstractFetcher<String> makeStringFetcher() {
return new StringFetcher();
}
public AbstractFetcher makeStringFetcher(){
返回新的StringFetcher();
}
您试图将返回值用作抽象获取程序
,这意味着您在编译时以任何方式知道类型
字符串
泛型是编译时的东西,编译器无法知道
类型
字符串的运行时值。因此,在这种情况下,您不能使用泛型类型安全。您在doSomething
中将AbstractFetcher
用作原始类型,这意味着将使用对其方法的擦除:
Object fetchOne();
List fetchMany();
而列表
可以转换为列表
(带有未选中的警告)。对象无法转换为字符串
最好是强类型工厂:
public AbstractFetcher<String> makeStringFetcher() {
return new StringFetcher();
}
public AbstractFetcher makeStringFetcher(){
返回新的StringFetcher();
}
您试图将返回值用作抽象获取程序
,这意味着您在编译时以任何方式知道类型
字符串
泛型是编译时的东西,编译器无法知道
类型
字符串的运行时值。因此,在这种情况下,您不能使用通用类型安全性。虽然仍有铸件,但在工厂中:
public class FetcherFactory {
public <T> AbstractFetcher<T> make(Class<T> type) {
if (type.equals(String.class)) {
return (AbstractFetcher<T>) new StringFetcher();
}
else {
return null;
}
}
}
公共类FetcherFactory{
公共抽象获取程序生成(类类型){
if(type.equals(String.class)){
返回(AbstractFetcher)新StringFetcher();
}
否则{
返回null;
}
}
}
然后你可以像这样打电话:
public void doSomething() {
List<String> list = factory.make(String.class).fetchMany();
String one = factory.make(String.class).fetchOne();
}
public void doSomething(){
List=factory.make(String.class).fetchMany();
stringone=factory.make(String.class).fetchOne();
}
虽然仍有铸件,但在工厂中:
public class FetcherFactory {
public <T> AbstractFetcher<T> make(Class<T> type) {
if (type.equals(String.class)) {
return (AbstractFetcher<T>) new StringFetcher();
}
else {
return null;
}
}
}
公共类FetcherFactory{
公共抽象获取程序生成(类类型){
if(type.equals(String.class)){
返回(AbstractFetcher)新StringFetcher();
}
否则{
返回null;
}
}
}
然后你可以像这样打电话:
public void doSomething() {
List<String> list = factory.make(String.class).fetchMany();
String one = factory.make(String.class).fetchOne();
}
public void doSomething(){
List=factory.make(String.class).fetchMany();
stringone=factory.make(String.class).fetchOne();
}
如果可以将类
而不是字符串参数传递给工厂,有一种方法可以实现这一点,而无需任何强制转换,但需要反射才能使其工作
实现FetcherFactory
如下:
public class FetcherFactory {
public <T, U extends AbstractFetcher<T>> AbstractFetcher<T> make(Class<U> type) {
try {
return type.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
公共类FetcherFactory{
公共抽象获取程序生成(类类型){
试一试{
返回类型:newInstance();
}捕获(实例化异常|非法访问异常e){
抛出新的运行时异常(e);
}
}
}
然后您可以在呼叫站点使用它,如下所示:
public class OneClass {
FetcherFactory factory;
public OneClass(FetcherFactory factory) {
this.factory = factory;
}
public void doSomething() {
List<String> list = factory.make(StringFetcher.class).fetchMany();
String one = factory.make(StringFetcher.class).fetchOne();
}
}
公共类OneClass{
菲克特工厂;
公共OneClass(FetcherFactory工厂){
这个工厂=工厂;
}
公共无效剂量测定法(){
List List=factory.make(StringFetcher.class).fetchMany();
stringone=factory.make(StringFetcher.class).fetchOne();
}
}
如果可以将类
而不是字符串参数传递给工厂,有一种方法可以实现这一点,而无需任何强制转换,但需要反射才能使其工作
实现FetcherFactory
如下:
public class FetcherFactory {
public <T, U extends AbstractFetcher<T>> AbstractFetcher<T> make(Class<U> type) {
try {
return type.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
公共类FetcherFactory{
公共抽象获取程序生成(类类型){
试一试{
返回类型:newInstance();
}捕获(实例化异常|非法访问异常e){
抛出新的运行时异常(e);
}
}
}