我在Code Review上问过这个问题,但有人暂停说这个问题更合适,所以问题是
假设我有一个应用程序,并且该应用程序有一个类,它从一个方法为我生成一个随机字符串,然后我从该字符串创建一个秘密。
代码类似于以下内容,
public class MyRandomStringGeneratorClass
{
private String generatedRandomString;
public String generateRandomString()
{
//some logic
this.generatedRandomString = someRandomStringGenerator();
}
public String generateSecretFromGeneratedRandomString()
{
//some encryption of the String 'generatedRandomString'
}
}
public class MainClass
{
public static void main(String args[])
{
MyRandomStringGeneratorClass obj = new MyRandomStringGeneratorClass();
String randomString = obj.generateRandomString();
String secretFromRandomString = obj.generateSecretFromGeneratedRandomString();
}
}
如果API的用户没有生成随机字符串并且事先调用了秘密生成器方法,则上述代码的问题就在于此。这将给他/她一个零指针错误,即
public class MainClass
{
public static void main(String args[])
{
MyRandomStringGeneratorClass obj = new MyRandomStringGeneratorClass();
// String randomString = obj.generateRandomString();
String secretFromRandomString = obj.generateSecretFromGeneratedRandomString();
}
}
我想在这种情况下我能做的最好的事情就是在字段的秘密生成器方法中进行空检查,如果它为null,则在控制台中将消息记录到用户必须生成字符串第一个从字符串中获取秘密,但这对我来说似乎有点陈词滥调。
即
public class MyRandomStringGeneratorClass
{
private String generatedRandomString;
public String generateRandomString()
{
//some logic
this.generatedRandomString = someRandomStringGenerator();
}
public String generateSecretFromGeneratedRandomString()
{
if(generatedRandomString==null)logSomeErrorAndReturn();
//some encryption of the String 'generatedRandomString'
}
}
我能想到的另一件事是从方法generateRandomString()
内部调用方法generateSecretFromGeneratedRandomString()
。这将确保确实生成了String,并且同样也执行了ecryption。
public class MyRandomStringGeneratorClass
{
private String generatedRandomString;
private String generateRandomString()
{
//some logic
this.generatedRandomString = someRandomStringGenerator();
}
public String generateSecretFromGeneratedRandomString()
{
generatedRandomString=generateRandomString();
// encrypt the String now
}
}
但是我可能无法返回普通生成的随机字符串(不将该字段声明为public或除非我为其提供getter方法)。 请建议适当的方式。询问是否需要进一步澄清。
答案 0 :(得分:0)
为什么还需要公开generateRandomString
?我只是将它作为一个实现细节,并将其封装在generateSecretFromGeneratedRandomString
:
public String generateSecretFromGeneratedRandomString() {
if (generatedRandomString == null) {
generatedRandomString = generateRandomString();
}
//some encryption of the String 'generatedRandomString'
return encryptedString;
}
答案 1 :(得分:0)
您可以尝试使用可选容器对象 - https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
public class MyRandomStringGeneratorClass
{
private Optional<String> generatedRandomString;
public String generateRandomString()
{
//some logic
this.generatedRandomString = Optional.of(someRandomStringGenerator());
return generatedRandomString.get()
}
public String generateSecretFromGeneratedRandomString()
{
if(generatedRandomString.isPresent())
{
//some encryption of the String 'generatedRandomString'
}
else
{
// generatedRandomString is null and you can create new one and encrypt it
}
}
}
答案 2 :(得分:0)
两者(generateRandomString和generateSecretFromGeneratedRandomString)方法都可以声明为public,以返回纯String和加密的String。如果之前未生成随机字符串,则从generateSecretFromGeneratedRandomString方法获取新的随机字符串。
答案 3 :(得分:0)
检查generateSecretFromGeneratedRandomString()方法中的Null值,如果值为null则抛出自定义异常,然后处理异常并要求用户在生成secret之前生成随机字符串。安全而简单。
答案 4 :(得分:0)
不可变的 RandomString 类怎么样:
public class RandomString {
private final String randomString;
private final String secret;
public RandomString() {
this.randomString = someRandomStringGenerator();
this.secret = computeSecret(this.randomString);
}
public String getString() {
return randomString;
}
public String getSecret() {
return secret;
}
}
public class MainClass {
public static void main(String args[]) {
final RandomString randomString = new RandomString();
System.out.println(randomString.getString());
System.out.println(randomString.getSecret());
}
}
答案 5 :(得分:0)
如果您希望强制执行序列并仍然保留覆盖两个微方法的选项,可以使用模板方法设计模式。
public class RndStringGenerator {
private String randomString;
public final String getSecretString() {
generateRndString();
return generateSecret();
}
public String getGeneratedRndString() {
if (randomString == null) {
generateRndString();
}
return randomString;
}
protected void generateRndString() {
// some logic
this.randomString = "Assume its Random String";
}
protected String generateSecret() {
// some encryption
return randomString;
}
}
这是Template方法,它允许覆盖受保护的方法,但会锁定最后的方法覆盖以维持序列。