As well known in java String class there is a length() method (why not getLength()?). If we look into this method we can see:
public int length() {
return value.length;
}
and value is an array. Why do we access a field? I know that this field is final and nobody can change it, but still what about polymorphism? And where can I see that field? In which class? I've found java.lang.reflect.Array,
but there is no such field as length.
Where can i see that field? In which class?
If you are looking for char array declaration
That's a char array declared on top. You can see that.
The value is used for character storage.
112
113 private final char value[];
And if you are looking for length field of an array
Array's are the part JVM implementation. You need to get the source code of JVM to analyze/see it.
And why we access a field?
That's how the length of an array can be known .
How about polymorthism? I know that this field is final and nobody can change it, but still what about polimorthis?
Never heard of it and if you mean Polymorphism, nothing to do here about it.
I think you might be expecting Java to be a pure OO language... It's not... It's a mixture of Objects and primitives. Primitives do not behave like objects and have language level native stuff, like public length fields etc.
Consider the following... a character array... Its length field is NOT a field in the traditional sense, it is baked into the language at the JVM level. This difference means that you cannot use reflection to access it via Field.getDeclaredField(). Java provides a special mechanism for this case - java.lang.reflect.Array.getLength(Object)
Object obj = new char[] { 'a', 'b' };
int length = ((char[]) obj).length; // .length looks like a field access but done by JVM
int lengthViaRelection = Array.getLength(obj);
This is very different from a standard field on a class where reflection can be used.
private static class ClassWithField {
public int length;
}
ClassWithField obj = new ClassWithField();
int length = obj.length; // .length is normal field access
int lengthViaRelection = (int) ClassWithField.class.getDeclaredField("length").get(obj);
value is an array of char (primitive, not java.lang.Character) and arrays of primitive types have a field named length:
final char[] chars = new char[1];
final int length = chars.length;
String is a final class, so extending String is not possible / permitted and the compiler won't let you do so.
The Strings private member(!) value is an array of chars (the primitive). This can be considered an implementation detail and you should not mess with it.
All arrays in Java got a field named length. It is accessible via property-access, there is no need for something like a "getter".
The length field of an array is not static; so each array will have its own field with its own value. The fact that it is readily has nothing to do with polymorphism; it's just a convenient way to find out information about the array.
The class java.lang.reflect.Array does not describe an array; it is a class that provides static methods to dynamically create and access Java arrays. So it is correct that there is no field length in that class.
Related
as I see it C++ constant pointer, C++ reference and Java final keyword (final on a variable) are all the same thing or at least act the same way.
they prevent the variable to change his "pointed address" but the internal value can be changed.
am I right for thinking that?
If not what are the differences?
regarding the c++ part
what are the differences between a constant pointer and a reference?
they look like a different way to do the same thing, why adding the reference concept to c++ if the concept already existed in the form of constant pointer?
regarding the Java part
is there a way(in Java) to simulate the same behavior of a pointer to a constant value of c++? basically is there a way to make constant values?
something more similar to const Shape* s = new Shape;
edit: I found at least 1 reason to introduce the reference concept
when we define a copy constructor we need to get the object as an argument and without a reference, we will get an infinite loop
C++:
class Shape{
public:
int member = 3;
};
Shape s1;
Shape s2;
Shape* const cp_var_1 = &s1;
cp_var_1->member = 5; // valid
cp_var_1 = &s2; //not valid
Shape& ref_var_2 = s1;
ref_var_2.member = 6; // valid - s1 changed as well
// cant change ref_var_2 to reference other variable (like s2)
ref_var_2 = s2;
// assignment operator called - s1 and s2 content are the same
// but ref_var_2 still reference s1
Java:
class Shape{
public int member = 3;
}
Shape s1 = new Shape();
Shape s2 = new Shape();
final Shape final_var_3 = s1;
final_var_3.member = 7; // valid
final_var_3 = s2; // not valid
Yes, you're precisely correct: in final var_3 = s1;, the final prevents you from ever making var_3 reference anything else, but you can dereference the variable and do whatever you want to what you find there: var_3.member = 7; is therefore valid (the dot is the dereference operator).
Note that the final keyword in java is used for different purposes. You can mark classes as final, which means they cannot be extended. (class Foo extends SomeClassMarkedFinal {} will not compile). final can also be applied to methods: In that case, it means any subclass may not override this method. Whilst the english name final does seem like a good term for all of this behaviour, the final as used on variable declarations, and the final as used on methods and classes, are otherwise utterly unrelated.
Many java types (such as java.lang.String, java.lang.Integer, and many more) are so-called 'immutable': These objects have absolutely no way to change anything about them. java's strings are objects (not ersatz char arrays), you can't access the underlying char array, there is no clear() or setChar() method, etc: Therefore, a final variable of type string is completely constant.
Java does not (currently) offer any way of marking a type as 'constant' in this sense, and it probably wouldn't make much sense to add this as a notion. For example, in java, java.io.File, which represents a file path, is immutable: It has absolutely no methods to mutate any of its state.
And yet, is it immutable? Is it 'constant'? If I run file.delete(), I can most assuredly observe a change, even though the object itself (which has just one field, of type string, containing a file path) hasn't changed at all.
The final keyword in java does have (basically) the same effect as a reference or constant pointer in c++, but const in c++ ends up being a lot more general and more powerful.
If you have a pointer or a reference to a const object, then the object itself should be regarded as immutable. For example, if a function takes a const reference to an object, I can safely pass in objects with the assumption that they won’t be modified. And if I write a const member function, then I’m promising that that member function won’t modify the underlying object.
Adding const to function parameters (especially those passed by reference or pointer) can make it a lot easier for programmers to reason about code. They know that they can expect those inputs to remain unchanged. This is an enormous benefit when tracking down bugs, and it makes it easier to reason about the interface for external libraries that use const properly.
Finally, unlike in Java, a function that takes a value by reference in C++ is allowed (and encouraged) to assume that the reference you passed it isn’t null. This is good. If you write your code so that your references are never null, the code will be simpler, cleaner, and faster (since you won’t have to do null checks) .
Why can't i be initialized before declaring it in code 1 but it can be in code 2 :
class Code1 {
void methodOfCode1() {
// System.out.println(i); can't use a local field before it is defined
// i = 10; can't initialize a local field before it is defined
int i;
}
}
class Code2{
static
{
i = 10; //A field can be initialized before it is defined.
}
static int i;
}
The answer is order of execution.
Code executes sequentially, you must define what something is before you use it. Therefore in a method you must declare a variable before you use it.
In Java the compiler initializes your class in multiple passes. It first runs through and declares all of the static members, then it sets the default values for all static members. This all happens before any methods (static or not) are executed.
It's the scope of the variable & the lack of type prior to its use: you have yet to define i. You must define a variable before it can be used:
int i = 0;
System.out.println(i); // works
System.out.println(j); // will not work
byte j;
Here's the Java Language Specification giving you the detail.
During initialise a variable, some amount of memory is allocated based on datatype.
Unless you allocate memory, you can't initialize value.
Because compiler must know where this variable is stored and how many bytes it have to use. If I tell computer var=97 before initializing, it cannot know where this "var" variable is stored. Also if "var" is char , computer needs one byte to store in RAM. However it also can be an integer which is 4 bytes(depends on different systems). Therefore, there would be an ambiguous situation for the system.Compiler does not allow that , reasonably.
Java is strongly-typed, you can't use something that you don't know what it is. For instance, a method is different if it receives a String or if it receives an int, so the compiler must be able to know which is the proper method to be invoked
For instance, this is valid:
public void dealWithIt(int val){
val++
System.out.println(val);
}
public void dealWithIt(String val){
System.out.println(val);
}
The compiler can't assign a value to a variable before know what type of variable it is.
In Java, a variable's type must be declared before it can be used.
For example:
System.out.println(i); // for this statement i is unknown/undefined...
i = 10; // same for above...
EDITED :
First inside class Code1,
you haven't declare variable before use it, which is against of Java Standard API so obviously compiler will complain.
while into class Code2 case,
you have declare 'static' both instance as well as block.
so it does not required any instance to load it.
(review static concept in depth will let you to the correct direction)
so I think I'm missing something. I am aware that
If no constructor is supplied java makes one for you.
If there's a constructor defined, default constructor by java is not used.
Constructor is used to initialize variables
Here's some simple code:
class a {
int f; // a variable with no value
int c; // a variable later initialized by the constructor
int b = 5; // this will be second question, a less important one
a(){
c = 1; // Constructor initiatives C, but not F
}
public static void main(String[] args){
a var = new a();
System.out.print(var.f); // Please see my comment below
}
}
Here's what I do not understand. Why is var.f printed? I did not initialize f in the constructor, however, there's no compile error and 0 value is initialed. I don't understand how '0' is initialized to 'f' despite me not having used it in constructor
Regarding b = 5, I understand what this code leads to, however, I do not think I understand what/who does the initialization here, is it new operator or something else? Thanks.
Edit: since the answers so far are not addressing my question
I am aware of the default values. I thought it was the default constructor that assigned them, is it not? If not, what assigns default values?
Java like most of programming languages has default values for uninitialized variables. Every numeric type of variable is initialized to 0-related value.
Boolean is false as default.
Strings and all of the objects have null as their default value.
Check docs for more info: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
int is a primitive data type. By definition, primitives cannot be null as they are not objects and will have a default value if not initialized. See here: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
If you want to be able to have a variable that is not initialized, you can use the object equivalent of an int java.lang.Integer
Instance variables that are declared but not initialised are given a default value.
References take a default value of null.
Primitives take a default value of zero
In regards to your query on your primitive int variable b, the new operator is not required, the new operator is used when instantiating a reference. When an instantiating a reference an object is created and memory is allocated on the JVM for that object.
Strings are a reference variable, but may be instantiated using the new keyword for example:
String example = new String("abc");
System.out.println(example); // prints abc.
Usually you would just write:
String example = "abc";
In the latter the literal is placed in to the 'string pool'...
You can read more about the string pool here: http://examples.javacodegeeks.com/core-java/lang/string/java-string-pool-example/
If no constructor is supplied java makes one for you.
Correct.
If there's a constructor defined, default constructor by java is not used.
It is not generated.
Constructor is used to initialize variables
Correct.
c = 1; // Constructor initiatives C, but not F
Untrue. Your code initializes c. The generated constructor initializes both.
I did not initialize f in the constructor
No, but Java did.
Java generates the following code for a constructor:
A super call.
Default initialization code for all variables declared without initializers. The default values are false, zero, or null as appropriate to the type.
Calls to all anonymous initializer blocks. (2) and (3) happen in textual order and can therefore be interleaved with each other.
Regarding b = 5, I understand what this code leads to, however, I do not think I understand what/who does the initialization here, is it new operator or something else?
See above.
I am aware of the default values. I thought it was the default constructor that assigned them, is it not?
No.
If not, what assigns default values?
The constructor. Any constructor.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Should I initialize variable within constructor or outside constructor
For example I have a field int x.
Does Java prefer the field to be initialized when it's declared
int x = 0;
or rather in the constructor?
public foo() {
x = 0;
}
Which is more preferred from a designing perspective?
Both are good, as long as you know what will happen.
The order in which they will be initialized is this:
Class members (like: public int x = 0;)
Constructors (like: this.x = 0;)
However, initializing integers to zero is a no-op. Java does this automatically.
A little demo to demonstrate an error of ignoring the order of initialization:
class Foo
{
public String str;
public String strTwo = "Here is str: " + str;
public Foo()
{
str = "Java";
System.out.println(strTwo);
}
}
This will print Here is str: null.
Instance variables of primitive types are initialized implicitly whereas reference variable are assigned with null values.
So if you want to assign like ::
int x=0;
it will be x=0 for all objects.
But in case of constructors you can initialize them with different value in different constructor, though its not a good practice to initialize with different values in different constructor.
Does Java prefer the field to be initialized when it's declared or rather in the constructor?
If you are initializing with default value, it'll be redundant to initialize either in constructor or at declaration time.
However, if you want to initialize with a value different from default value, constructor should be used over delaration.
Which is more preferred from a designing perspective?
From design point of view, No difference at all. It is implementaiton detail.
My preference is to initialize default values outside constructor like
int x=0;
So that if you have multiple constructors and lot of instance variables, you won't forgot to initialize. In-case if I require specific value to variable, then I will re-initialize in constructor.
From what I recall, the bytecode produced by the compiler in both instances is pretty much identical, and it is really just a matter of preference and coding style. Personally, I tend to prefer to initialize variables in the constructor - In some cases you will have to initialize variables in a constructor anyway (Such as when passing in arguments to a constructor), and it means you need only look in one place to understand what is going on, rather than 2.
(On a side note - in your example there is no need to do "int x = 0" since defining "int x;" will automatically have it set to 0.)
public foo() {
x = 0;
}
this will be good. if u use this int x =0 it will be for all objects. but the constructor notation is for objects which are created by that particular constructors.
class Test {
public static void main(String[] args) throws Exception {
Test t = new Test();
System.out.println(t.field);
System.out.println(t.getClass().getField("field").get(t));
int[] ar = new int[23];
System.out.println(ar.length);
System.out.println(ar.getClass().getField("length").get(ar));
}
public int field = 10;
};
When I run the above code, I get the following result on the command line --
10
10
23
Exception in thread "main" java.lang.NoSuchFieldException: length
at java.lang.Class.getField(Class.java:1520)
at Test.main(Test.java:9)
How come I am unable to access the field "length" in the array?
There is an special java.lang.reflect.Array Class. length is no normal field. To access it there is a special method getLength.
I think this might be a bug in the JVM implementation. Here is my reasoning:
According to the documentation for Class.getField, getField should, as part (1) of its search algorithm, find length if it was declared as a public field: "If C declares a public field with the name specified, that is the field to be reflected."
According to the Java Language Specification, every array has length declared as "The public final field length, which contains the number of components of the array."
Since this field is declared as having name length, getField should either throw a SecurityException as documented, or should return the Field object.
Now interestingly, the Class.getFields method explicitly mentions that "The implicit length field for array class is not reflected by this method. User code should use the methods of class Array to manipulate arrays." This does not seem to parallel getField, so this could either be a misreading on my part or just bad documentation.
Hope this helps!
In Java, arrays are just simple objects. Object don't have any field called length. That's why the reflection is failing.
Please see http://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html for more information on how arrays are implemented.
From the documentation ...
An array's length is not part of its type.