我有以下两种方法:
public class LoaderService {
public static Config loadConfigFile() {
try (var jsonReader = new JsonReader(new FileReader(Path.PROJECT_RESOURCES + "config" + Extension.JSON))) {
return new Gson().fromJson(jsonReader, Config.class);
} catch (IOException e) {
return Config.builder().build();
}
}
public static UriContainer loadUriContainerFile() {
try (var jsonReader = new JsonReader(new FileReader(Path.PROJECT_RESOURCES + "URI container" + Extension.JSON))) {
return new Gson().fromJson(jsonReader, UriContainer.class);
} catch (IOException e) {
return UriContainer.builder().build();
}
}
}
正如您所看到的,主体是相同的——我可以通过方法参数传递文件名。这些方法从JSON文件加载内容。他们身体上唯一的显著区别是所应用的课程类型<我想到了类似的事情:
public class LoaderService<T> {
public T loadFile(String fileName) {
try (var jsonReader = new JsonReader(new FileReader(fileName))) {
return new Gson().fromJson(jsonReader, T.class);
} catch (IOException e) {
return T.builder().build();
}
}
但是我有错误:
return T.builder().build();
// ---> Cannot resolve method 'builder' in 'T'
我的dto-例如配置:
package dto;
import lombok.Builder;
import lombok.Value;
@Value
@Builder
public class Config {
String url;
String username;
String password;
String jdbcDriverPath;
String driverClassName;
String hostname;
String port;
String serverPath;
}
有可能在上述情况下应用泛型吗<对不起,如果这个问题没有意义,因为我只是在学习泛型
您想要的是不可能的,因为您无法抽象静态方法的概念。
为什么你认为“FooFactory”是一个java迷因?工厂就是这样:抽象出构建器方法的概念。
然而,如果发生任何异常,只返回一个“空白”实例的想法似乎是极不明智的。这个错误有无数个原因,当然“扔掉所有关于这个错误的信息并返回一个空白实例”是一个很好的公式,可以花上几个小时追踪bug,一个只做奇怪事情的应用程序,因为代码一直在运行,当意外事件发生时会丢弃调试信息。
也许您打算只在该文件不存在的特定场景中返回一个空白实例。在这种情况下,我将捕获FileNotFoundException
。
将名为loadFile
的方法声明为抛出IOException
是100%合理的。如果您发现调用者中存在“烦人”问题,请记住,publicstaticvoidmain
应该声明为抛出异常。
您需要抽象构建器的概念,或者至少抽象“使我成为默认空白实例”的概念。
让我们使用供应商(它被称为供应商,但我们在这里使用它作为工厂):
public static <T> T loadFile(Class<T> type, Supplier<T> defaultMaker) {
try (var jsonReader = new JsonReader(new FileReader(fileName))) {
return new Gson().fromJson(jsonReader, type);
} catch (IOException e) {
// I really, really wouldn't do this, but...
return defaultMaker.get();
}
}
为什么
T.class
不起作用?为什么T.builder()
不起作用?因为泛型是javac想象出来的。运行时不知道。大多数泛型都被彻底删除了(它们无法在编译中生存),而在没有的地方,就java而言,它就是。exe
是一个注释。
因此,
不可能工作。Java对T一无所知。它可以是任何东西。它显然可以是没有T. class
?这是不可能的:T是编译时的东西,而不是运行时的东西。Javac不知道T是什么,因此T. class是不可能的。同样的论点解释了为什么T. Builder()Builder()
方法的类型。
因此,泛型最好被认为是一种“链接”工具。它把事情联系起来。因此,如果你只在一个地方使用泛型,它是无用的,或者是一个丑陋的黑客。
通过拥有类
如果您仔细考虑,运行时不需要知道t是什么。这是一条需要记住的有用规则:如果你的代码不能工作,除非运行时知道t是什么,那么你就不能这样做。
泛型是复杂的;默认情况下,它们是不变的(子类型不是任何给定类型的有效替换;这与普通类型不同,在普通类型中,您可以将字符串表达式等指定给Object类型的变量。在泛型中则不是这样;您不能指定
List类型的表达式
这个错误会花费你几天的时间,所以,修复它,记住它,更新你的IDE来标记它。
永远不要使用
文件阅读器
1
这门课不合目的。如果您的IDE具有“禁止”事物的功能(如果您使用它,则将其标记为错误),则添加它。
问题是,FileReader使用平台默认编码,谁知道这可能是什么。JSON需要UTF_8。
正确的做法是:
Files.newBufferedReader(filePath)
而不是
新建文件读取器
。这是因为文件
默认为UTF-8,而不是“平台默认值”。或者,
newjsonreader(newinputstreamreader)(newfileinputstream(fileName)),标准字符集。UTF_8))
。
请注意,如果您在一个默认为UTF-8的平台上,则不可能测试此错误,然而,当有人在一个没有(大多数平台都没有)的平台上运行您的代码时,它会在您的脸上爆炸尝试读取包含非ASCII字符的JSON文件。
这些缺陷会造成巨大的损失,因为您没有对它们进行测试,所以它们往往会投入生产。
[1] 从JDK11开始,有一个采用字符集的
FileReader
构造函数。然而,JDK11(实际上是JDK8)有了新的文件API,这是一个重大改进。因此,没有理由使用FileReader:在过时的JDK版本上,由于使用了平台默认编码(如果目的是将其视为JSON,那么这是错误的),它会被破坏,而在现代JDK版本上,有更好的替代方案。不管怎样,FileReader都是错误的答案。
因此,上述结构在ClassA中也同样存在。 假设我想编码2个其他类ClassC(使用ClassA的实例)和ClassD(使用ClassB的实例)。除了ClassA和ClassB的实例之外,ClassC和ClassD的代码完全相同。 从示例中可以看出,ClassC和ClassD具有相同的功能,但对tmp使用了不同的类
我有两个数据类型不同的方法,但正文相同。我没有使用任何。我只使用这些方法来引发异常。有没有什么方法可以将这两种方法结合起来,或者有什么方法可以优化代码? PS:我不想使用接口或一些具有普通逻辑的新方法。
在JLS 8第8.4.8.1节中,有一条声明: 在某些参数化下,泛型超类C中的具体方法可以与该类中的抽象方法具有相同的签名。在这种情况下,具体方法是继承的,而抽象方法不是。然后应将继承的方法视为覆盖其来自C的抽象对等体。 有人能为泛型类提供这种参数化的例子吗?我不能。
我想说得具体一点。我有一个名为Result的类和一个名为Result的派生类 这些类在方法中用作返回类型。为此,我创建了这个helper类: 正如您所看到的,上面的代码对于成功有两种返回类型,一种是如果您不想返回任何东西,另一种是如果您想返回一些东西,但是失败的结果永远不会返回什么东西。这是不必要的,只是一个错误消息。这使我想到以下问题:当我想创建一个可以使用返回类型返回Success,而不使用返
我有一个采访问题-C#,是否可以在一个类中实现,从接口继承有两个具有相同名称和相同签名的方法?
我有以下的方法,这是添加产品使用注入的服务!它是在静态调用内部调用的,因此它是静态的! 它工作良好,但我需要使它通用,以便我可以使用不同的服务与它。像这样的东西! 然而,第二个方法抱怨AddProduct方法不明确,不确定如何确保它从相关服务调用了正确的方法!