[ 
https://issues.apache.org/jira/browse/LANG-1822?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

尹茂椿萱 updated LANG-1822:
-----------------------
    Description: 
There is an inconsistency between:
 * {{NumberUtils.isCreatable(String)}}
 * {{NumberUtils.createNumber(String)}}

Specifically, {{isCreatable}} returns {{true}} for certain numeric strings, but 
{{createNumber}} fails to parse the same input and throws a 
{{{}NumberFormatException{}}}.

Additionally, there are cases where {{createNumber}} successfully parses a 
string, but {{isCreatable}} returns {{{}false{}}}.

This violates the expected contract:
{quote}If {{isCreatable(str)}} returns {{{}true{}}}, then {{createNumber(str)}} 
should successfully return a {{{}Number{}}}.
{quote}
h2. Steps to Reproduce

 

@Test public void test()

{ System.out.println(NumberUtils.isCreatable("#10"));

Number number = NumberUtils.createNumber("#10");

System.out.println(number.longValue());

System.out.println(NumberUtils.isCreatable("+1l"));

Number number1 = NumberUtils.createNumber("+1l");

System.out.println(number1.longValue()); }
----
h2. Actual Results

 

false
16
true
Exception in thread "main" java.lang.NumberFormatException: +1l is not a valid 
number.
----
h2. Expected Results
h3. Case 1: {{"#10"}}
 * Either:
 ** {{isCreatable("#10")}} should return {{{}true{}}},
 * Or:
 ** {{createNumber("#10")}} should throw an exception

h3. Case 2: {{"+1l"}}
 * Since {{{}isCreatable("+1l") == true{}}}, then:
 ** {{createNumber("+1l")}} should successfully return a {{Number}} (e.g., 
{{{}Long{}}})

----
h2. Analysis
h3. Issue 1: Hex format inconsistency
 * {{"#10"}} is interpreted as a hexadecimal number ({{{}16{}}}) by 
{{createNumber}}
 * But {{isCreatable("#10")}} returns {{false}}

→ {{isCreatable}} does not recognize {{{}#{}}}-prefixed hexadecimal numbers, 
while {{createNumber}} does
----
h3. Issue 2: Signed long literal inconsistency
 * {{"+1l"}} is considered creatable ({{{}true{}}})
 * But {{createNumber}} throws {{NumberFormatException}}

→ {{isCreatable}} accepts the format, but {{createNumber}} cannot parse it
----
h2. Impact
 * Breaks API consistency
 * Makes {{isCreatable}} unreliable as a validation method
 * Can lead to unexpected runtime exceptions

Typical unsafe usage pattern:

 

{{if (NumberUtils.isCreatable(str)) {
Number n = NumberUtils.createNumber(str); // may throw exception
}}}
----
h2. Suggested Fix

Ensure both methods follow consistent parsing rules:
h3. Option 1 (Preferred)
 * Align {{createNumber}} with {{isCreatable}}
 ** Support:
 *** {{+}} prefix combined with {{l/L}} suffix
 *** {{#}} hexadecimal notation

h3. Option 2
 * Restrict {{isCreatable}} to match {{createNumber}}
 ** Return {{false}} for:
 *** {{"+1l"}}
 *** {{"#10"}}

  was:
There is an inconsistency between:
 * {{NumberUtils.isCreatable(String)}}
 * {{NumberUtils.createNumber(String)}}

Specifically, {{isCreatable}} returns {{true}} for certain numeric strings, but 
{{createNumber}} fails to parse the same input and throws a 
{{{}NumberFormatException{}}}.

Additionally, there are cases where {{createNumber}} successfully parses a 
string, but {{isCreatable}} returns {{{}false{}}}.

This violates the expected contract:
{quote}If {{isCreatable(str)}} returns {{{}true{}}}, then {{createNumber(str)}} 
should successfully return a {{{}Number{}}}.
{quote}
h2. Steps to Reproduce

 

{{@Test
public void test() \{
    System.out.println(NumberUtils.isCreatable("#10"));
    Number number = NumberUtils.createNumber("#10");
    System.out.println(number.longValue());

    System.out.println(NumberUtils.isCreatable("+1l"));
    Number number1 = NumberUtils.createNumber("+1l");
    System.out.println(number1.longValue());
}}}
----
h2. Actual Results

 

{{false
16
true
Exception in thread "main" java.lang.NumberFormatException: +1l is not a valid 
number.}}
----
h2. Expected Results
h3. Case 1: {{"#10"}}
 * Either:
 ** {{isCreatable("#10")}} should return {{{}true{}}},
 * Or:
 ** {{createNumber("#10")}} should throw an exception

h3. Case 2: {{"+1l"}}
 * Since {{{}isCreatable("+1l") == true{}}}, then:
 ** {{createNumber("+1l")}} should successfully return a {{Number}} (e.g., 
{{{}Long{}}})

----
h2. Analysis
h3. Issue 1: Hex format inconsistency
 * {{"#10"}} is interpreted as a hexadecimal number ({{{}16{}}}) by 
{{createNumber}}
 * But {{isCreatable("#10")}} returns {{false}}

→ {{isCreatable}} does not recognize {{{}#{}}}-prefixed hexadecimal numbers, 
while {{createNumber}} does
----
h3. Issue 2: Signed long literal inconsistency
 * {{"+1l"}} is considered creatable ({{{}true{}}})
 * But {{createNumber}} throws {{NumberFormatException}}

→ {{isCreatable}} accepts the format, but {{createNumber}} cannot parse it
----
h2. Impact
 * Breaks API consistency
 * Makes {{isCreatable}} unreliable as a validation method
 * Can lead to unexpected runtime exceptions

Typical unsafe usage pattern:

 

{{if (NumberUtils.isCreatable(str)) \{
    Number n = NumberUtils.createNumber(str); // may throw exception
}}}
----
h2. Suggested Fix

Ensure both methods follow consistent parsing rules:
h3. Option 1 (Preferred)
 * Align {{createNumber}} with {{isCreatable}}
 ** Support:
 *** {{+}} prefix combined with {{l/L}} suffix
 *** {{#}} hexadecimal notation

h3. Option 2
 * Restrict {{isCreatable}} to match {{createNumber}}
 ** Return {{false}} for:
 *** {{"+1l"}}
 *** {{"#10"}}


> Inconsistency between NumberUtils.isCreatable and createNumber
> --------------------------------------------------------------
>
>                 Key: LANG-1822
>                 URL: https://issues.apache.org/jira/browse/LANG-1822
>             Project: Commons Lang
>          Issue Type: Bug
>    Affects Versions: 3.20.0
>            Reporter: 尹茂椿萱
>            Priority: Major
>
> There is an inconsistency between:
>  * {{NumberUtils.isCreatable(String)}}
>  * {{NumberUtils.createNumber(String)}}
> Specifically, {{isCreatable}} returns {{true}} for certain numeric strings, 
> but {{createNumber}} fails to parse the same input and throws a 
> {{{}NumberFormatException{}}}.
> Additionally, there are cases where {{createNumber}} successfully parses a 
> string, but {{isCreatable}} returns {{{}false{}}}.
> This violates the expected contract:
> {quote}If {{isCreatable(str)}} returns {{{}true{}}}, then 
> {{createNumber(str)}} should successfully return a {{{}Number{}}}.
> {quote}
> h2. Steps to Reproduce
>  
> @Test public void test()
> { System.out.println(NumberUtils.isCreatable("#10"));
> Number number = NumberUtils.createNumber("#10");
> System.out.println(number.longValue());
> System.out.println(NumberUtils.isCreatable("+1l"));
> Number number1 = NumberUtils.createNumber("+1l");
> System.out.println(number1.longValue()); }
> ----
> h2. Actual Results
>  
> false
> 16
> true
> Exception in thread "main" java.lang.NumberFormatException: +1l is not a 
> valid number.
> ----
> h2. Expected Results
> h3. Case 1: {{"#10"}}
>  * Either:
>  ** {{isCreatable("#10")}} should return {{{}true{}}},
>  * Or:
>  ** {{createNumber("#10")}} should throw an exception
> h3. Case 2: {{"+1l"}}
>  * Since {{{}isCreatable("+1l") == true{}}}, then:
>  ** {{createNumber("+1l")}} should successfully return a {{Number}} (e.g., 
> {{{}Long{}}})
> ----
> h2. Analysis
> h3. Issue 1: Hex format inconsistency
>  * {{"#10"}} is interpreted as a hexadecimal number ({{{}16{}}}) by 
> {{createNumber}}
>  * But {{isCreatable("#10")}} returns {{false}}
> → {{isCreatable}} does not recognize {{{}#{}}}-prefixed hexadecimal numbers, 
> while {{createNumber}} does
> ----
> h3. Issue 2: Signed long literal inconsistency
>  * {{"+1l"}} is considered creatable ({{{}true{}}})
>  * But {{createNumber}} throws {{NumberFormatException}}
> → {{isCreatable}} accepts the format, but {{createNumber}} cannot parse it
> ----
> h2. Impact
>  * Breaks API consistency
>  * Makes {{isCreatable}} unreliable as a validation method
>  * Can lead to unexpected runtime exceptions
> Typical unsafe usage pattern:
>  
> {{if (NumberUtils.isCreatable(str)) {
> Number n = NumberUtils.createNumber(str); // may throw exception
> }}}
> ----
> h2. Suggested Fix
> Ensure both methods follow consistent parsing rules:
> h3. Option 1 (Preferred)
>  * Align {{createNumber}} with {{isCreatable}}
>  ** Support:
>  *** {{+}} prefix combined with {{l/L}} suffix
>  *** {{#}} hexadecimal notation
> h3. Option 2
>  * Restrict {{isCreatable}} to match {{createNumber}}
>  ** Return {{false}} for:
>  *** {{"+1l"}}
>  *** {{"#10"}}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to