Why is string.length() a method, and int[].length a property? [duplicate] - java

This question already has answers here:
length and length() in Java
(8 answers)
Closed 10 years ago.
Why is String.length() a method, and int[].length a property (see below)?
int[] nums = {2,4,7,12,43};
String phrase = "Hello, world.";
System.out.length(nums.length);
System.out.length(phrase.length());

I don't think there has to be a good reason, and I think there could be many reasons.
But one is that by making String#length() a property, it can be declared in an interface instead (in this case CharSequence). Interfaces cannot declare public instance fields.

This is what the String::length() function looks like:
public int length() {
return count;
}
So essentially count could've been called length and made public to be similar to arrays (it is final after all).
It was probably just a design decision. There may have been some contributing factors that we can speculate about (one of which could've been the CharSequence thing mentioned by Mark Peters).

Because String is not an array as such. The designers of Java designed arrays (which are objects) to have a public field named length.
On the other hand, a String has a method which gives the length instead. In general it is a more conventional approach to make member fields private and use methods to access them, but in the case of arrays it is not.
They're different objects with different signatures as far as you are concerned. A String is not a char[] (although internally it might be implemented that way).

No particular reason, I think. In fact in C#, a very similar language, String.length is a property http://msdn.microsoft.com/en-us/library/system.string.length.aspx. But take a look at what C# designer has to say about this design:
The Length property returns the number of Char objects in this instance, not the number of Unicode characters.
The reason is that a Unicode character might be represented by more than one Char. Use the
System.Globalization.StringInfo class to work with each Unicode character instead of each Char.

Why int[].length a property?
Arrays are special objects in java, they have a simple attribute named length which is final.
There is no "class definition" of an array (you can't find it in any .class file), they're a part of the language itself.
The public final field length, which contains the number of components of the array. length may be positive or zero.
The public method clone, which overrides the method of the same name in class Object and throws no checked exceptions. The return type of the clone method of an array type T[] is T[].
A clone of a multidimensional array is shallow, which is to say that it creates only a single new array. Subarrays are shared.
All the members inherited from class Object; the only method of Object that is not inherited is its clone method.
Resource: JSL 10.7
Why String.length() a method?

Related

What does the output of explicitly printing an array in java mean? [duplicate]

This question already has answers here:
How do I print my Java object without getting "SomeType#2f92e0f4"?
(13 answers)
Closed 9 months ago.
First of all, yes, I know I have to iterate through an array and print its elements one by one in order to actually "print" an array. I was just wondering what the output of explicitly printing an array such as in the code below actually means. My guess is that it's the memory location of the array?
I know it's a fairly newbie question but I'm new to java (and coding in general) so please enlighten me.
public class Tests {
public static void main(String[] args) {
String[] strArray = {"1", "2", "3"};
System.out.println(strArray);
}
}
The println(Object) method invokes Object::toString on its parameter, so you are really asking about the meaning of the toString method on arrays. And arrays do not override toString, so the result comes from the implementation of toString in Object.
The default implementation of toString includes the name of the object's class and a numeric representation derived from its object identity. In the absence of a better toString, this allows you to see the object's type, as well as be able to differentiate different instances (since they'll have different identities). This is a "least common denominator" approach; it is a reasonable minimum the system can provide.
It's the default toString method of Object class.
It's the name of the class plus # plus the return value of hashCode method, which may be implemented differently in every class.

How did JVM implement array's class?

Can I override any methods of array?
For example toString() or other methods.
import java.lang.reflect.Method;
public class ArraysClassTest {
static int[] array = { 1, 2, 3, 1 };
public static void main(String[] args) {
Class<? extends int[]> class1 = array.getClass();
try {
Method method = class1.getMethod("toString");
} catch (NoSuchMethodException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
You can't change any features of arrays. JLS §10.7 Array Members specifies every member of an array:
The members of an array type are all of the following:
The public final field length, which contains the number of components of the array. length may be positive or zero.
The public method clone, which overrides the method of the same name in class Object and throws no checked exceptions. The return type of the clone method of an array type T[] is T[].
A clone of a multidimensional array is shallow, which is to say that it creates only a single new array. Subarrays are shared.
All the members inherited from class Object; the only method of Object that is not inherited is its clone method.
The specification doesn't allow any way of customizing this implementation. An array's toString() method, for example, is always the basic one inherited from Object.
To create an array object the compiler emits one of three instructions into the compiled Java bytecode: newarray for primitives, anewarray for reference types, or multinewarray for all multidimensional arrays. In implementing those instructions, the virtual machine creates each array class as needed at runtime (JVMS §5.3.3 Creating Array Classes). The VM also defines dedicated bytecode instructions for the compiler to use for getting and setting elements of arrays and getting an array's length.
How the arrays are implemented within the VM is not specified whatsoever. It is purely an implementation detail, and even the Java compiler doesn't know, or care. The actual code involved depends on the flavor of virtual machine you're running your program on, the version of that VM, the OS and CPU it's running on, and any relevant runtime options the VM is configured with (e.g., whether in interpreted mode or not).
A quick look over the OpenJDK 8 source code turns up some of the relevant machinery for arrays:
src/share/vm/oops/arrayKlass.cpp
src/share/vm/oops/objArrayKlass.cpp
src/share/vm/oops/typeArrayKlass.cpp
src/share/vm/interpreter/bytecodeInterpreter.cpp – implements bytecode instructions for the interpreter, including instructions for creating and accessing arrays. It's tortuous and intricate, however.
src/share/vm/c1/c1_RangeCheckElimination.cpp – performs some clever array bounds check eliminations when compiling from bytecode to native code.
As arrays are a core feature of the language and the VM, it's impossible to point to any one source file and say "here, this is the class Array code". Arrays are special, and the machinery that implements them is literally all over the place.
If you want to customize the behavior of an array, the only thing you can do is not use the array directly, but use, subclass, or write, a collection class that internally contains the array. That gives you complete freedom to define the class's behavior and performance characteristics. However, it is impossible to make a custom class be an array in the Java language sense. That means you can't make it implement the [] operator or be passable to a method that expects an array.
In Java, all arrays (including those of primitive types) have java.lang.Object as their base class. (For one thing this is how zero length arrays can be modelled).
Although it's possible to override any method in that base class, Java itself specifies the form of the array. You are not able to interfere with that: in particular you can't extend an array.
To answer your direct question: no, you can't.
Arrays are a "compiler" construct - the compiler knows what String[] means; and it creates the corresponding byte code out of that. You can only create array objects, but not "new array classes". Or beyond that, the JVM knows what to do about "array using" bytecode instructions.
In other words: the source code that defines the behavior of Array-of-something objects is completely out of your control. Arrays just do what arrays do; no way for you to interfere with that.
And to get to your implicit question why things are this way:
Sometimes there isn't much to understand; but simply to accept. Thing is that the Java language was created almost 20+ years ago; and at some point, some folks made some design choices. Many of them were excellent; some of them might have been handled if we would redo things nowadays.
You will find for example, that Scala has a different way of dealing with arrays. But for java, things are as they are; and especially for things that are "so core" to the language as arrays, there is simply no sense in changing any of that nowadays.
You can create a proxy and use it in place of the original object
final int[] array = { 1, 2, 3, 1 };
Object proxy = Proxy.newProxyInstance(array.getClass().getClassLoader(), array.getClass().getInterfaces(), new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
StringBuilder b=new StringBuilder("the array is");
for(int i:array)
b.append(" ").append(i);
return b.toString();
}
});
System.out.println(proxy.toString());
the output of the above is "the array is 1 2 3 1".

What is the difference in using .length and .length() to find length [duplicate]

This question already has answers here:
How can I get the size of an array, a Collection, or a String in Java?
(3 answers)
Closed 8 years ago.
The former (.length) isn't even a function , how does it return length?
The reason length isn't function in an array is that it is a field. In particular, a public final one as specified by the Java Language Specification section 10.7.
While ArrayList (ad Vector of the 1.0 libraries) have a length() method, the key thing to realize is that this value can change. You call add(Object o) on a Vector, and you've changed its length.
On the other hand, you can't change the length of an array.
Once an array object is created, its length never changes. To make an array variable refer to an array of different length, a reference to a different array must be assigned to the variable.
(from JLS Section 10.2 - Array Variables)
And thus, the simplest thing that works is to make the length a field. One that is public and can't change.
Realize in the Java 1.0 days, HotSpot wasn't quite as advanced as it is today. It wouldn't be able to do all the optimizations that it can now with inlining methods. And thus, to make array access that much faster for situations that needed it, its a field.
Related reading on Stack Overflow: length and length() in java

What's the difference between length and length()? [duplicate]

This question already has answers here:
length and length() in Java
(8 answers)
Closed 6 years ago.
I've noticed that when doing the length of an array you write something like:
arrayone.length;
However, for such things as array lists or a string, you write a bracket on the end, such as the following for the length of the String:
stringone.length();
What is the key reason for this and how do you know when to put the brackets or now?
.length;
directly accesses a field member.
.length();
invokes a method (i.e. an accessor) to access a field member.
in the case of String, this is to be expected since it's immutable.
Arrays are handled differently than Strings or ArrayLists or anything else that can be counted in Java. An Array is pretty much a native type and it's length can never be changed after it is initialized, so there's no need for encapsulation. The length variable can be directly exposed with no side effects.
The reason why String uses a method instead of a variable is because it internally uses a char[] that it doesn't want to expose publicly (for immutability/encapsulation), so it wraps the length variable in a length() method. It's the same reason ArrayList has a size() method instead of a length variable.
The only time you'll use the variable instead of the method is with arrays. Everything else will be methods. That is, you'll use the brackets for everything except arrays.
The only true way to know when to use which one is experience. Though an IDE with autocompletion will usually help you out when you don't remember.
For the most part (not always) array.length, System.out, and System.err are the most common 3 you'll run into that are actually member access instead of method calls.
int[] myArray = new int[10];
String myString = "hello world!";
List<int> myList = new ArrayList<int>();
myArray.length //gives the length of the array
myString.length() //gives the length of the string
myList.size() //gives the length of the list
Its very likely that strings and arrays were designed at different times and hence ended up using different conventions. One justification is that since Strings use arrays internally a method length() was used to avoid duplication of the same information. Ultimately this is just an inconsistently that evolved that would definitely be fixed if the language were ever redesigned from the ground up. :D
The main difference is that in the A) first case its Array Type for example int[], Object[], double[], ect.. that has a public field called lenght and the B) second case is a Object String that has a function called length(), the function could of been called getLength() or something else. The array type public field length is probably a hangover from C++ way of doing things.
Array Types have the following:
The public final field length, which contains the number of
components of the array (length may be positive or zero)
The public method clone, which overrides the method of the same name
in class Object and throws no checked exceptions
All the members inherited from class Object; the only method of
Object that is not inherited is its clone method
Take a look at this, Array Types.
.length() is a method of a String class and which returns the number of characters in the string.
.length will give the number of elements stored in an array.
public class length
{
public static void main(String args[])
{
String x="test";
int a[]={1,2,3,4};
System.out.println(x.length());
System.out.println(a.length);
}
}
// output
4
4
length is a pseudo-data member reference, and only works for (small-a) arrays (ignoring classes that you may define that implement the member).
Everything else is an object of a class, and all JDK classes that have this concept define either length() or size() instance methods. (I do wish they'd been consistent and picked one or the other, but that's water over the bridge.)
Array.length is a property of that Array, similar to a variable reference.
ArrayList.size() is an actual method call to the array list object.

Difference between byte[] and byte ... in Java Methods

Someone asked me what the difference between the two method parameters and why you would use the ... over specifically assigned array.
putMessage(byte ...send)
putMessage(byte[] send)
I couldn't answer them with confidence and couldn't remember what the ... is called.
The ... in your first example are called varargs. Your second example has an array argument. Varargs are a convenience for times when you want to hard code a variable number of arguments to a method but don't want to manually create an array to hold them. It's a shorthand notation. Consider this:
putMessage(0b00100101, 0b00100101, 0b00100101); // varargs
vs. this:
putMessage(new byte[] { 0b00100101, 0b00100101, 0b00100101 }); // array
The first example is less cluttered and more readable.
The parameters with ellipses are generally referred to as "varargs" if you want to google that.
Using varargs allows you to call a method with variable number of arguments without having to specify an array e.g.
public void printStr(String ...strings) {
for (String s : strings) {
System.out.println(s);
}
}
> printStr("Hello", "World")
Hello
World
So varargs allow a certain degree of convenience, but there are downsides - the varargs parameter must be the last parameter in the method signature, and thus you cannot have more than one varargs parameter to a method. If you want to pass multiple arrays to a method you have to use arrays, not varargs.
Another reason you might see arrays in some places where you might expect varargs is that varargs were only introduced in Java 5 - older code and code that needs to be backwards compatible will still be using arrays even where it might make more sense conceptually to use varargs.
The advantage of using varargs in the method signature is flexibility - there are some situations where the caller will have an array ready anyway and some where they will just have several arguments. Varargs will accept either the array or each variable as a separate argument, saving the caller the trouble of instantiating and populating an array.
The first one is with Varargs.
In short
A. First can be used to call with single byte type arg, 2 byte args.. or many args or an array.
B. second will be used with array only.
The ellipsis (three dots) indicates that you are using "varargs".
See http://download.oracle.com/javase/1,5.0/docs/guide/language/varargs.html for more details.
Inside the method, you access the elements of "send" as an array. The two methods are the same in that regard. The convenience is for the caller. In the second putMessage, the caller is compelled to create an array of bytes to pass to putMessage. In the first putMessage, the caller can simply say "putMessage(byte1, byte2)" or "putMessage(byte1, byte2, byte3)" or "putMessage(byte1)" -- variable number of arguments, or varargs.
The ellipses (...) allow you to inline N parameters of a type to a function call without having to define an array first. In the end you do simply get an array of parameters but it's basically shorthand or syntactic sugar. Also your client code might be a little cleaner and more declarative with the ellipses syntax... though it could easily go the other way and become mucky and unreadable.
Here's a great example of the ellipses syntax (variable length argument lists.) While looking at the sample consider what the client code (in the main function) would look like if an array was used instead of a variable length argument list.

Categories

Resources