[L Array Notation - Where Does It Come From

[L array notation - where does it come from?

[ stands for Array, the Lsome.type.Here; represent the type of the array. That's similar to the type descriptors used internally in the bytecode seen in §4.3 of the Java Virtual Machine Specification -- . The only difference is in that the real descriptors use / rather than . for denoting packages.

For instance, for primitives the value is: [I for array of ints, a two-dimensional array would be: [[I (strictly speaking Java doesn't have real two-dimensional arrays, but you can make arrays that consist of arrays).

Since classes may have any name, it would be harder to identify what class it is so they are delimited with L, followed by the class name and finishing with a ;

Descriptors are also used to represent the types of fields and methods.

For instance:

(IDLjava/lang/Thread;)Ljava/lang/Object;

... corresponds to a method whose parameters are int, double, and Thread and the return type is Object

edit

You can also see this in .class files using the java dissambler

C:>more > S.java
class S {
Object hello(int i, double d, long j, Thread t ) {
return new Object();
}
}
^C
C:>javac S.java

C:>javap -verbose S
class S extends java.lang.Object
SourceFile: "S.java"
minor version: 0
major version: 50
Constant pool:
const #1 = Method #2.#12; // java/lang/Object."<init>":()V
const #2 = class #13; // java/lang/Object
const #3 = class #14; // S
const #4 = Asciz <init>;
const #5 = Asciz ()V;
const #6 = Asciz Code;
const #7 = Asciz LineNumberTable;
const #8 = Asciz hello;
const #9 = Asciz (IDJLjava/lang/Thread;)Ljava/lang/Object;;
const #10 = Asciz SourceFile;
const #11 = Asciz S.java;
const #12 = NameAndType #4:#5;// "<init>":()V
const #13 = Asciz java/lang/Object;
const #14 = Asciz S;

{
S();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0

java.lang.Object hello(int, double, long, java.lang.Thread);
Code:
Stack=2, Locals=7, Args_size=5
0: new #2; //class java/lang/Object
3: dup
4: invokespecial #1; //Method java/lang/Object."<init>":()V
7: areturn
LineNumberTable:
line 3: 0

}

And in raw class file ( look at line 5 ):

Sample Image

Reference: Field description on the JVM specification

What is the formulation for Java Array class names?

One letter for each primitive, one symbol for arrays, and one letter for reference:

  • I = int
  • J = long
  • D = double
  • F = float
  • Z = boolean
  • C = char
  • B = byte
  • S = short
  • Lcom/foo/Thing; = reference 'com.foo.Thing'
  • [ = array of whatever is next (so, [[I is an int[][]).

This is VM-speak for type signatures. For example, the signature of:

public boolean[] foo(String[] args, int count) { ... }

is: ([Ljava/lang/String;I)[Z.

It is for machines and not humans; it is easy to parse (you just move forward, no need to look-ahead).

This is not the 'class name' of a thing; the usual name for this construct is 'vm name'. Note that generics just disappear from these; the VM name of List<String> is Ljava/util/List;. It's why you can't override methods if the two methods end up with the same name, param types, and return type if you remove all generics.

What is the purpose to use array notation to access object property in for..in loop?

Using the property accessor is like using a literal:

var obj= {  prop1: "Hello",  name: "This is not prop1"}
var prop1="name";
console.log(obj.prop1)console.log(obj[prop1])

Where does the magic of singleton arrays come from?

The basic answer is that for an a = Array(T) Julia always allocates sizeof(T)*length(a)+40 bytes. Since sizeof(Missing) == 0, this means it doesn't allocate any bytes related to the length.

Indexing occurs on line 569 of array.c, and the relevant line is

jl_value_t *r = undefref_check((jl_datatype_t*)eltype, jl_new_bits(eltype, &((char*)a->data)[i * a->elsize]))

When the size of the array is zero, a->data[i * a->elsize] refers to the beginning of a->data. The content of this is, however, completely irrelevant: when eltype has zero jl_datatype_size, jl_new_bits ignores the data pointer and instead returns the instance field from the eltype, which is the singleton object.

Pseudocode array notation confusion

That you think is correct, this is a list by comprehesion definition, and (a, b) is a set with the a and b value.

More info: https://en.wikipedia.org/wiki/List_comprehension

Example in haskell: https://wiki.haskell.org/List_comprehension

What is this: [Ljava.lang.Object;?

[Ljava.lang.Object; is the name for Object[].class, the java.lang.Class representing the class of array of Object.

The naming scheme is documented in Class.getName():

If this class object represents a reference type that is not an array type then the binary name of the class is returned, as specified by the Java Language Specification (§13.1).

If this class object represents a primitive type or void, then the name returned is the Java language keyword corresponding to the primitive type or void.

If this class object represents a class of arrays, then the internal form of the name consists of the name of the element type preceded by one or more '[' characters representing the depth of the array nesting.
The encoding of element type names is as follows:

Element Type        Encoding
boolean Z
byte B
char C
double D
float F
int I
long J
short S
class or interface Lclassname;

Yours is the last on that list. Here are some examples:

// xxxxx varies
System.out.println(new int[0][0][7]); // [[[I@xxxxx
System.out.println(new String[4][2]); // [[Ljava.lang.String;@xxxxx
System.out.println(new boolean[256]); // [Z@xxxxx

The reason why the toString() method on arrays returns String in this format is because arrays do not @Override the method inherited from Object, which is specified as follows:

The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:

getClass().getName() + '@' + Integer.toHexString(hashCode())

Note: you can not rely on the toString() of any arbitrary object to follow the above specification, since they can (and usually do) @Override it to return something else. The more reliable way of inspecting the type of an arbitrary object is to invoke getClass() on it (a final method inherited from Object) and then reflecting on the returned Class object. Ideally, though, the API should've been designed such that reflection is not necessary (see Effective Java 2nd Edition, Item 53: Prefer interfaces to reflection).


On a more "useful" toString for arrays

java.util.Arrays provides toString overloads for primitive arrays and Object[]. There is also deepToString that you may want to use for nested arrays.

Here are some examples:

int[] nums = { 1, 2, 3 };

System.out.println(nums);
// [I@xxxxx

System.out.println(Arrays.toString(nums));
// [1, 2, 3]

int[][] table = {
{ 1, },
{ 2, 3, },
{ 4, 5, 6, },
};

System.out.println(Arrays.toString(table));
// [[I@xxxxx, [I@yyyyy, [I@zzzzz]

System.out.println(Arrays.deepToString(table));
// [[1], [2, 3], [4, 5, 6]]

There are also Arrays.equals and Arrays.deepEquals that perform array equality comparison by their elements, among many other array-related utility methods.

Related questions

  • Java Arrays.equals() returns false for two dimensional arrays. -- in-depth coverage


Related Topics



Leave a reply



Submit