Why is out of range not thrown for 'substring(startIndex, endIndex)'
According to the Java API doc, substring throws an error when the start index is greater than the Length of the String.
IndexOutOfBoundsException - if
beginIndex is negative or larger than
the length of this String object.
In fact, they give an example much like yours:
"emptiness".substring(9) returns "" (an empty string)
I guess this means it is best to think of a Java String as the following, where an index is wrapped in |
:
|0| A |1| B |2| C |3| D |4| E |5|
Which is to say a string has both a start and end index.
Both start index and end index are out of range but the substring method still works in Java
Acording to the documentation of the method:
Throws:
IndexOutOfBoundsException - if beginIndex is negative or larger than the length of this String object.
The length of your string is 1 and not 0, so it doens't throw and exception.
Java substring: 'string index out of range'
I"m guessing i'm getting this error
because the string is trying to
substring a Null value. But wouldn't
the ".length() > 0" part eliminate
that issue?
No, calling itemdescription.length() when itemdescription is null would not generate a StringIndexOutOfBoundsException, but rather a NullPointerException since you would essentially be trying to call a method on null.
As others have indicated, StringIndexOutOfBoundsException indicates that itemdescription is not at least 38 characters long. You probably want to handle both conditions (I assuming you want to truncate):
final String value;
if (itemdescription == null || itemdescription.length() <= 0) {
value = "_";
} else if (itemdescription.length() <= 38) {
value = itemdescription;
} else {
value = itemdescription.substring(0, 38);
}
pstmt2.setString(3, value);
Might be a good place for a utility function if you do that a lot...
System.ArgumentOutOfRangeException: Length cannot be less than zero
This is a frequent mistake in .NET when using the Substring method. People often think that the Substring takes the start and end index which is wrong. It takes the start index and the length. For example:
string str = "ABC123";
int length = str.Length - str.IndexOf("1") + 1;
string sub = str.Substring(0, length); // ABC1
Or better, create an extension method for this reusable piece to add the Java Like Substring in C# that takes a start and end index:
public static class MyExtensions
{
public static string SubstringRange(this string str, int startIndex, int endIndex)
{
if (startIndex > str.Length - 1)
throw new ArgumentOutOfRangeException(nameof(startIndex));
if (endIndex > str.Length - 1)
throw new ArgumentOutOfRangeException(nameof(endIndex));
return str.Substring(startIndex, endIndex - startIndex + 1);
}
}
Usage:
string str = "ABC123";
string sub2 = str.SubstringRange(str.IndexOf("B"), str.IndexOf("2")); // BC12
Substring strange Bounds?
Okay people have been throwing java doc around but that doesn't really answer the question.
The reason you can do "D".substring(1)
is because you're asking for the string starting at index 1, to index 1 (exclusive). This is by definition the empty string as its size is 1-1=0. Every string has an empty string at the start, end and between every character. E.g. "" + "B" + "O" + "" + "B" + ""
= "BOB"
.
Why java substring doesn't crash?
Per http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#substring(int)
Throws: IndexOutOfBoundsException - if beginIndex is negative or
larger than the length of this String object.
here, your string is of length 1, your index is 1 and it is not negative => no exception thrown.
A little unintuitive? Yes. But substring() is a little unintuitive with its index choices in general :-)
Cannot invoke initializer for type 'RangeString.Index' with an argument list of type '(RangeString.Index)'
Some background:
In Swift 3, additional range types were introduced, making a total
of four (see for example Ole Begemann: Ranges in Swift 3):
Range, ClosedRange, CountableRange, CountableClosedRange
With the implementation of SE-0143 Conditional conformances in Swift 4.2, the “countable” variants
are not separate types anymore, but (constrained) type aliases, for example
public typealias CountableRange<Bound: Strideable> = Range<Bound>
where Bound.Stride : SignedInteger
and, as a consequence, various conversions between the different
range types have been removed, such as the
init(_ other: Range<Range.Bound>)
initializer of struct Range
. All theses changes are part of the
[stdlib][WIP] Eliminate (Closed)CountableRange using conditional conformance (#13342) commit.
So that is the reason why
let range: Range<Index> = Range<Index>(start..<self.endIndex)
does not compile anymore.
How to fix
As you already figured out, this can be simply fixed as
let range: Range<Index> = start..<self.endIndex
or just
let range = start..<self.endIndex
without the type annotation.
Another option is to use a one sided range
(introduced in Swift 4 with SE-0172 One-sided Ranges):
extension String {
func index(of aString: String, startingFrom position: Int = 0) -> String.Index? {
let start = index(startIndex, offsetBy: position)
return self[start...].range(of: aString, options: .literal)?.lowerBound
}
}
This works because the substring self[start...]
shares its indices
with the originating string self
.
Related Topics
How to Take Screenshots Fast in Java
Java: Split String When an Uppercase Letter Is Found
What Is the Java Equivalent of Sscanf for Parsing Values from a String Using a Known Pattern
Where Are Generic Types Stored in Java Class Files
Why Aren't Integers Cached in Java
Why Does Getrealpath() Return Null When Deployed with a .War File
Parsing a Hexadecimal String to an Integer Throws a Numberformatexception
Best Practices to Create and Download a Huge Zip (From Several Blobs) in a Webapp
Java: Why am I Required to Initialize a Primitive Local Variable
Understanding the etc/Gmt Time Zone
How Read Doc or Docx File in Java
JPA SQL Server No Dialect Mapping for Jdbc Type: -9
Functional Interface That Takes Nothing and Returns Nothing
Cancelling a Long Running Regex Match
How to Implement Task Prioritization Using an Executorservice in Java 5
Any Simple Way to Explain Why I Cannot Do List<Animal> Animals = New Arraylist<Dog>()