在JAVA中动态确定用户输入数据类型
我编写了以下代码来确定用户输入的数据类型 更新:删除对在JAVA中动态确定用户输入数据类型,java,json,Java,Json,我编写了以下代码来确定用户输入的数据类型 更新:删除对浮点的解析,因为双精度值也可以解析为浮点,代价是@DodgyCodeException提到的精度 import java.util.Scanner; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; public class Main { public static void main(String[] arg
浮点的解析
,因为双精度
值也可以解析为浮点
,代价是@DodgyCodeException提到的精度
import java.util.Scanner;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class Main {
public static void main(String[] args) {
Scanner src = new Scanner(System.in);
String input;
System.out.println("Enter input:");
input = src.nextLine();
System.out.println("You entered:" + getDataType(input));
}
private static String getDataType(Object input) {
try {
JSONObject obj = new JSONObject((String) input);
return "JSONObject";
} catch (JSONException ex) {
try {
JSONArray array = new JSONArray(input);
return "JSONArray";
} catch (JSONException ex0) {
try {
Integer inti = Integer.parseInt((String) input);
return "Integer";
} catch (NumberFormatException ex1) {
try {
Double dub = Double.parseDouble((String) input);
return "Double";
} catch (NumberFormatException ex3) {
return "String";
}
}
}
}
}
}
}
我必须反复运行此操作数百次,我已经了解到捕获异常
是一项昂贵的操作。有没有更好的方法来实现这一点 我想知道输入是否是json/jsonarray 您需要处理
JSONException
来确定JSON类型,然后您可以使用方法来确定其他类型,如下所示:
private static String getDataType(String input) {
try {
return getJsonObjectType(input);
} catch (JSONException ex1) {
try {
return getJsonArrayType(input);
} catch (JSONException ex2) {
return getNonJsonType(input);
}
}
}
private static String getJsonArrayType(String input) throws JSONException {
new JSONArray(input);
return "JSONArray";
}
private static String getJsonObjectType(String input) throws JSONException {
new JSONObject((String) input);
return "JSONObject";
}
private static String getNonJsonType(String input) {
try {
return getNumberType(input);
} catch(ParseException ex3) {
return "String";
}
}
private static String getNumberType(String input) throws ParseException {
Number number = NumberFormat.getInstance().parse(input);
if(number instanceof Long) {
if(number.longValue() < Integer.MAX_VALUE) {
return "int";
} else {
return "long";
}
} else {
if(number.doubleValue() < Float.MAX_VALUE) {
return "float";
} else {
return "double";
}
}
}
私有静态字符串getDataType(字符串输入){
试一试{
返回getJsonObjectType(输入);
}捕获(JSONException ex1){
试一试{
返回getJsonArrayType(输入);
}捕获(JSONException ex2){
返回getNonJsonType(输入);
}
}
}
私有静态字符串getJsonArrayType(字符串输入)抛出JSONException{
新JSONArray(输入);
返回“JSONArray”;
}
私有静态字符串getJsonObjectType(字符串输入)抛出JSONException{
新的JSONObject((字符串)输入);
返回“JSONObject”;
}
私有静态字符串getNonJsonType(字符串输入){
试一试{
返回getNumberType(输入);
}捕获(解析异常ex3){
返回“字符串”;
}
}
私有静态字符串getNumberType(字符串输入)引发异常{
Number=NumberFormat.getInstance().parse(输入);
如果(长的实例数){
if(number.longValue()
老实说,我不喜欢通过解析器的异常来确定类型的想法。我将为每种格式构建一个模式,并对所有格式进行迭代,以检查给定的字符串是否与其中一个匹配
类似于Scanner
类的工作方式,但它相当复杂。很难写出涵盖所有可能情况的正则表达式
但如果准备好正则表达式,则算法很简单:
public class Main {
private final Map<String, String> patterns = Map.of(
"Integer", integerPattern()
);
public String getDataType(String input) {
for (Map.Entry<String, String> entry : patterns.entrySet()) {
if (Pattern.matches(entry.getValue(), input)) {
return entry.getKey();
}
}
return "Unknown";
}
}
我很确定你可以用谷歌搜索所有的正则表达式,或者在这里找到它们
但是,如果有一个“更轻”的解决方案,或者您只是不想使用regex方法,该怎么办
通过引入地图
,您可以混合使用不同的技术:
主类{
私有最终映射谓词=Map.of(
“整数”,这个::isInteger,
“JSON”,这个::isJSON
);
公共字符串getDataType(字符串输入){
for(Map.Entry谓词:谓词.entrySet()){
if(谓词.getValue().test(输入)){
返回谓词.getKey();
}
}
返回“未知”;
}
私有布尔值isJSON(字符串输入){
返回LibraryClass.isJSON(输入);
}
专用布尔isInteger(字符串输入){
试一试{
整数值(输入);
}捕获(数字格式){
返回false;
}
返回true;
}
}
我相信它更具可读性,它降低了嵌套级别,并将不同的逻辑封装在不同的方法中。我的方法是让框架完成它的工作,并使用它以通用的方式解析输入:
Object obj = new org.json.JSONTokener(input).nextValue();
if (obj instanceof JSONArray)
return "JSONArray";
if (obj instanceof JSONObject)
return "JSONObject";
if (obj instanceof Integer)
return "Integer"
...
可能使用switch
语句或Map
而不是一长串if
结构。并捕获无效JSON输入的JSONException
也许可以简化为返回
obj.getClass()
或obj.getClass().getSimpleName()
,以获得与您现在拥有的功能几乎相同的功能。其长短是:
- 在不捕获这些异常的情况下,没有合理的方法来封装这个确切的功能
- 如果您正在谈论将该方法“数百次”运行,那么它真的不应该成为性能瓶颈。如果是,则对其进行基准测试,找出该方法中的瓶颈所在,然后具体解决这些瓶颈
parseInt()
真的没有其他明智的方法了。但是,如果您只想知道某个东西是否是数字,可以使用正则表达式:
str.matches("\\d+"); //Returns true if it's a whole positive number
str.matches("-?\\d+"); //Returns true if it's a whole number
(其他正则表达式很容易在网上计算/找到十进制数、带指数的数字等)
或者您可以对其进行流式处理,并分别检查每个字符:
str.chars().allMatch(c->Character.isDigit(c));
或者,您可能希望使用来自Apache Commons的(
isparsable()
,以及该类上的其他方法)预先结束或替换异常检查。您是否尝试过instanceof(如果可能的话),这是错误的做法。您不必优化您编写的所有内容。特别是不要过早地使用String
而不捕获ClassCastException
。如果您知道它肯定是一个字符串,为什么不将参数设置为字符串呢?成功地将其解析为浮点值
,并不意味着数字不能是精度更高的双精度
。pa
str.matches("\\d+"); //Returns true if it's a whole positive number
str.matches("-?\\d+"); //Returns true if it's a whole number
str.chars().allMatch(c->Character.isDigit(c));