Java 不确定类型的参数数量不确定
Java indeterminate number of arguments of indeterminate type
我的公司有一个应用程序服务器,它以自己定制的 XTML 语法接收指令集。由于这是有限的,所以有一个特殊的 "drop to Java" 命令可以将参数发送到 JVM (1.6.0_39)。参数仅作为 "in" 或 "in/out" 传递,其中特殊的 "in/out" 变量是用于此平台的可变库。
以前接收外部配置的唯一方法是使用不同的特殊命令从 XTML 文件中读取。由于不值得深入研究的原因,这种配置方法很难扩展,所以我正在研究一种使用 Java.
来实现的方法
此配置的语法是 (String,T) 的二元组,其中 String 是 XTML 文件中的 属性 名称,T 是应用程序服务器将要使用的 in/out 可变变量将 属性 值分配给。
我正在尝试尽可能无缝地进行此转换,而不必在应用程序服务器中进行烦人的字符串解析。
我已经有一个功能
public String[] get(String ... keys)
从应用程序服务器的键中检索值,但我真正需要的是一个函数
public static void get(T ... args)
接受二元组。但是,请注意它需要是 static 才能从应用程序服务器调用,我的理解是 T 不能用于静态上下文。
我不知道如何以不需要(至少)两个步骤的方式解决这个问题,并且没有办法循环应用程序服务器中的参数。
我知道我是在一组严格的限制下工作,所以如果答案是 "you have to some messed up stuff",那很好 - 我只是想了解另一种方式。
-- 编辑--
正在编辑更具体的示例。
配置是一组键值对,可以在数据库或文件中。 get函数是:
public JSONObject get(String ... keys) throws ClassNotFoundException, SQLException, KeyNotFoundException, FileNotFoundException, IOException {
JSONObject response = new JSONObject();
if(this.isDatabase) {
for(int i=0;i<keys.length;i++){
PreparedStatement statement = this.prepare("SELECT value FROM "+this.databaseSchema+"."+this.settingsTableName+" WHERE key = ? LIMIT 1");
statement.setString(1, keys[i]);
ResultSet results = statement.executeQuery();
boolean found = false;
while(results.next()){
String value = results.getString("value");
value = value.replace("\"","");
response.put(keys[i], value);
found = true;
}
if(!found){
throw new KeyNotFoundException(keys[i]);
}
}
} else if (this.isFile) {
boolean[] found = new boolean[keys.length];
BufferedReader br = new BufferedReader(new FileReader(this.settingsFile));
String line;
while((line = br.readLine()) != null ){
String key;
String value;
for(int i=0;i<line.length();i++){
if(line.charAt(i) == '='){
key = line.substring(0,i);
value = line.substring(i+1,line.length());
if(indexOfString(keys,key) != -1){
value = value.replace("\"","");
found[indexOfString(keys,key)] = true;
response.put(key,value);
if(allFound(found)==-1){
return response;
}
}
break;
}
}
}
if(allFound(found)!=-1){
throw new KeyNotFoundException(keys[allFound(found)]);
}
}
return response;
如果我有办法,它看起来像...
// ConfigurationReader.java
public class ConfigurationReader{
public ConfigurationReader( ... ){}
public static JSONObject get(String key){
// Get the key
}
}
// ConfigurationInterface.java
public static void get(T ... args){
ConfigurationReader cfgReader = new ConfigurationReader( ... );
for(var i=0;i<args.length;i+=2){
in = args[i];
out = args[i+1];
out = cfgReader.get(in);
}
}
您可以在静态上下文中使用泛型。您的问题有点 vague/unclear 关于您打算如何执行此操作,但请考虑以下示例:
public class Example {
public static void main(String[] args) {
Type t1 = new Type("foo");
Type t2 = new Type("bar");
Type t3 = new Type("baz");
Printer.<Type> printNames(t1, t2, t3);
}
public static class Printer {
@SafeVarargs
public static <T extends Type> void printNames(T... objs) {
for (T obj : objs) {
System.out.println(obj);
}
}
}
public static class Type {
private final String name;
public Type(String name) {
this.name = name;
}
@Override
public final String toString() {
return name;
}
}
}
Printer.<Type> printNames(t1, t2, t3)
对 printNames
方法进行静态引用,使用 Type
泛型进行参数化。
请注意,此 是 类型安全的。尝试将不同类型的对象传递给该参数化方法将在编译时失败(假设此时已知类型不同):
Example.java:8: error: method printNames in class Printer cannot be applied to given types;
Printer.<Type> printNames(t1, t2, t3, "test");
^
required: T[]
found: Type,Type,Type,String
reason: varargs mismatch; String cannot be converted to Type
where T is a type-variable:
T extends Type declared in method <T>printNames(T...)
编辑
根据您的评论,问题不在于您尝试对方法参数使用 generic 类型(在 Java 意义上无论如何,通用词);您只是在寻找 String
和您的自定义类型都继承自的任何非特定父 class 。只有一个 class:Object
.
我 强烈建议 如果您有任何灵活性,请重新考虑您的设计,因为这会导致 API 设计不佳。但是,您可以使用 Object... objs
.
让您的方法接受任意数量的任意类型的对象
例如:
public class Example {
public static void main(String[] args) {
Printer.printNames("a", "b", new Type("foo"), new Type("bar"));
}
public static class Printer {
public static void printNames(Object... objs) {
for (Object obj : objs) {
if (obj instanceof String) {
System.out.println(((String) obj).toUpperCase());
}
else if (obj instanceof Type) {
System.out.println(obj);
}
}
}
}
public static class Type {
private final String name;
public Type(String name) { this.name = name; }
public final String toString() { return name; }
}
}
根据@nbrooks 的工作,我找到了解决方案。我做了一个临时的 MutableString(将被库提供的 类 替换)。
public static class MutableString {
public String value;
public MutableString(){}
}
// One for every mutable type
public static void Pair(String key, MutableString mutable, ApplicationConfiguration appConfig) throws Exception{
mutable.value = appConfig.get(key).toString();
}
public static void Retrieve(Object ... args) throws Exception {
ApplicationConfiguration appConfig = new ApplicationConfiguration( ##args## );
for(int i=0;i<args.length;i+=2){
if(args[i+1].getClass().equals(new MutableString().getClass())){
ApplicationConfiguration.Pair( (String) args[i], (MutableString) args[i+1], appConfig);
} // One for every mutable type
}
}
我的公司有一个应用程序服务器,它以自己定制的 XTML 语法接收指令集。由于这是有限的,所以有一个特殊的 "drop to Java" 命令可以将参数发送到 JVM (1.6.0_39)。参数仅作为 "in" 或 "in/out" 传递,其中特殊的 "in/out" 变量是用于此平台的可变库。
以前接收外部配置的唯一方法是使用不同的特殊命令从 XTML 文件中读取。由于不值得深入研究的原因,这种配置方法很难扩展,所以我正在研究一种使用 Java.
来实现的方法此配置的语法是 (String,T) 的二元组,其中 String 是 XTML 文件中的 属性 名称,T 是应用程序服务器将要使用的 in/out 可变变量将 属性 值分配给。
我正在尝试尽可能无缝地进行此转换,而不必在应用程序服务器中进行烦人的字符串解析。
我已经有一个功能
public String[] get(String ... keys)
从应用程序服务器的键中检索值,但我真正需要的是一个函数
public static void get(T ... args)
接受二元组。但是,请注意它需要是 static 才能从应用程序服务器调用,我的理解是 T 不能用于静态上下文。
我不知道如何以不需要(至少)两个步骤的方式解决这个问题,并且没有办法循环应用程序服务器中的参数。
我知道我是在一组严格的限制下工作,所以如果答案是 "you have to some messed up stuff",那很好 - 我只是想了解另一种方式。
-- 编辑--
正在编辑更具体的示例。
配置是一组键值对,可以在数据库或文件中。 get函数是:
public JSONObject get(String ... keys) throws ClassNotFoundException, SQLException, KeyNotFoundException, FileNotFoundException, IOException {
JSONObject response = new JSONObject();
if(this.isDatabase) {
for(int i=0;i<keys.length;i++){
PreparedStatement statement = this.prepare("SELECT value FROM "+this.databaseSchema+"."+this.settingsTableName+" WHERE key = ? LIMIT 1");
statement.setString(1, keys[i]);
ResultSet results = statement.executeQuery();
boolean found = false;
while(results.next()){
String value = results.getString("value");
value = value.replace("\"","");
response.put(keys[i], value);
found = true;
}
if(!found){
throw new KeyNotFoundException(keys[i]);
}
}
} else if (this.isFile) {
boolean[] found = new boolean[keys.length];
BufferedReader br = new BufferedReader(new FileReader(this.settingsFile));
String line;
while((line = br.readLine()) != null ){
String key;
String value;
for(int i=0;i<line.length();i++){
if(line.charAt(i) == '='){
key = line.substring(0,i);
value = line.substring(i+1,line.length());
if(indexOfString(keys,key) != -1){
value = value.replace("\"","");
found[indexOfString(keys,key)] = true;
response.put(key,value);
if(allFound(found)==-1){
return response;
}
}
break;
}
}
}
if(allFound(found)!=-1){
throw new KeyNotFoundException(keys[allFound(found)]);
}
}
return response;
如果我有办法,它看起来像...
// ConfigurationReader.java
public class ConfigurationReader{
public ConfigurationReader( ... ){}
public static JSONObject get(String key){
// Get the key
}
}
// ConfigurationInterface.java
public static void get(T ... args){
ConfigurationReader cfgReader = new ConfigurationReader( ... );
for(var i=0;i<args.length;i+=2){
in = args[i];
out = args[i+1];
out = cfgReader.get(in);
}
}
您可以在静态上下文中使用泛型。您的问题有点 vague/unclear 关于您打算如何执行此操作,但请考虑以下示例:
public class Example {
public static void main(String[] args) {
Type t1 = new Type("foo");
Type t2 = new Type("bar");
Type t3 = new Type("baz");
Printer.<Type> printNames(t1, t2, t3);
}
public static class Printer {
@SafeVarargs
public static <T extends Type> void printNames(T... objs) {
for (T obj : objs) {
System.out.println(obj);
}
}
}
public static class Type {
private final String name;
public Type(String name) {
this.name = name;
}
@Override
public final String toString() {
return name;
}
}
}
Printer.<Type> printNames(t1, t2, t3)
对 printNames
方法进行静态引用,使用 Type
泛型进行参数化。
请注意,此 是 类型安全的。尝试将不同类型的对象传递给该参数化方法将在编译时失败(假设此时已知类型不同):
Example.java:8: error: method printNames in class Printer cannot be applied to given types;
Printer.<Type> printNames(t1, t2, t3, "test");
^
required: T[]
found: Type,Type,Type,String
reason: varargs mismatch; String cannot be converted to Type
where T is a type-variable:
T extends Type declared in method <T>printNames(T...)
编辑
根据您的评论,问题不在于您尝试对方法参数使用 generic 类型(在 Java 意义上无论如何,通用词);您只是在寻找 String
和您的自定义类型都继承自的任何非特定父 class 。只有一个 class:Object
.
我 强烈建议 如果您有任何灵活性,请重新考虑您的设计,因为这会导致 API 设计不佳。但是,您可以使用 Object... objs
.
例如:
public class Example {
public static void main(String[] args) {
Printer.printNames("a", "b", new Type("foo"), new Type("bar"));
}
public static class Printer {
public static void printNames(Object... objs) {
for (Object obj : objs) {
if (obj instanceof String) {
System.out.println(((String) obj).toUpperCase());
}
else if (obj instanceof Type) {
System.out.println(obj);
}
}
}
}
public static class Type {
private final String name;
public Type(String name) { this.name = name; }
public final String toString() { return name; }
}
}
根据@nbrooks 的工作,我找到了解决方案。我做了一个临时的 MutableString(将被库提供的 类 替换)。
public static class MutableString {
public String value;
public MutableString(){}
}
// One for every mutable type
public static void Pair(String key, MutableString mutable, ApplicationConfiguration appConfig) throws Exception{
mutable.value = appConfig.get(key).toString();
}
public static void Retrieve(Object ... args) throws Exception {
ApplicationConfiguration appConfig = new ApplicationConfiguration( ##args## );
for(int i=0;i<args.length;i+=2){
if(args[i+1].getClass().equals(new MutableString().getClass())){
ApplicationConfiguration.Pair( (String) args[i], (MutableString) args[i+1], appConfig);
} // One for every mutable type
}
}