Master test = new Inner();
System.out.println(test.getClass());
In the above example the Inner class extends the Master class, but what I'm confused about is that test.getClass() returns Inner, but isn't test really of the type Master? Other than the constructor no methods/properties can be used from the Inner class, only what's in the Master class. Furthermore the constructor for Inner actually sets properties exclusive to Inner, but somehow these properties don't exist in test even though it uses the constructor -- which doesn't seem like it should work.
For example if define the classes as:
public class Master {
public int number = 0;
public Master() {
number = 9;
}
}
public class Inner extends Master {
public int innerNumber = 0;
public Inner() {
number = 1;
innerNumber = 2;
}
}
test will use Inner's constructor which sets innerNumber, but test.innerNumber doesn't even exist because innerNumber isn't apart of the Master type. Also, test.getClass() says it's of the Inner type, not Master.
Object.getClass() returns the class object of the dynamic type of the object, not the static type (the type of the variable or attribute you declared it).
Hence new Inner().getClass() returns Inner.class, new Master().getClass() returns Master.class no matter what the type of the variable is that holds the reference.
Question 1:
Master test = new Inner();
The above line indicates that get method implementation's from Inner class (ovveriding). So Inner classes getClass() method calls.
Question 2:
test.innerNumber
Inheritance happens from Parent to Child. innerNumber is a property of Inner(child). Master(Parent) won't get it.
Related
Below is a piece of code which provides an example of using inner class in Java.
I would like to know how the inner class instance iterator is created and linked to the arrayOfInts array.
DataStructureIterator iterator = this.new EvenIterator();
I understand that the 'ds' instance is created by the constructor of DataStructure class, but the iterator instance is of DataStructureIterator type. It seems not quite reasonable that a DataStructureIterator instance can be constructed by a constructor of another class.
Full code here:
public class DataStructure {
// Create an array
private final static int SIZE = 15;
private int[] arrayOfInts = new int[SIZE];
public DataStructure() {
// fill the array with ascending integer values
for (int i = 0; i < SIZE; i++) {
arrayOfInts[i] = i;
}
}
public void printEven() {
// Print out values of even indices of the array
DataStructureIterator iterator = this.new EvenIterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
}
interface DataStructureIterator extends java.util.Iterator<Integer> { }
// Inner class implements the DataStructureIterator interface,
// which extends the Iterator<Integer> interface
private class EvenIterator implements DataStructureIterator {
// Start stepping through the array from the beginning
private int nextIndex = 0;
public boolean hasNext() {
// Check if the current element is the last in the array
return (nextIndex <= SIZE - 1);
}
public Integer next() {
// Record a value of an even index of the array
Integer retValue = Integer.valueOf(arrayOfInts[nextIndex]);
// Get the next even element
nextIndex += 2;
return retValue;
}
}
public static void main(String s[]) {
// Fill the array with integer values and print out only
// values of even indices
DataStructure ds = new DataStructure();
ds.printEven();
}
}
This is a question from the Oracle's Java documents, here is the source: https://docs.oracle.com/javase/tutorial/java/javaOO/innerclasses.html
From your Q:
It seems not quite reasonable that a DataStructureIterator instance can be constructed by a constructor of another class.
In your code, the instance of the DataStructureIterator is actually not created by the DataStructure constructor. It is created whenever the DataStructure instance method printEven is called:
public void printEven() {
// Print out values of even indices of the array
DataStructureIterator iterator = this.new EvenIterator();
// Omitted for brevity
}
But it could also be created in the constructor as a field or set with a default value e.g.:
public class DataStructure {
private DataStructureIterator iterator = new EvenIterator();
// Omitted for brevity
}
If your inner class (EventIterator) was public, it could also be created "outside" of DataStructure:
// In some other Java class
DataStructure ds = new DataStructure();
DataStructure.EventIterator iterator = ds.new EventIterator();
The key thing is that outer class (DataStructure) instance is created first.
As the docs note:
To instantiate an inner class, you must first instantiate the outer class
This is because the instance of an inner class is always tied to the outer/parent class.
From your Q:
I would like to know how the inner class instance iterator is created and linked to the arrayOfInts array.
The key thing is that an instance of a inner non-static class is that always has access to the parent instance's methods/fields.
As the docs also state (emphasis added):
As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields.
As such, the instance of the DataStructureIterator can access the DataStructure field arrayOfInts.
But note that if you created a separate DataStructure instance e.g. ds2, then the DataStructureIterator instance within ds2 will have access to ds2.arrayOfInts but it won't have access to the ds.arrayOfInts. In your code the values of arrayOfInts will be the same but the instances are actually different (try allowing arrayOfInts to be set via the DataStructure constructor).
If DataStructureIterator was defined as a nested static class, then it won't automatically have access to arrayOfInts and it would need arrayOfInts passed in as an arg to its constructor or to its method.
You can think of inner non-static classes as a logical grouping of code for the parent (DataStructure class) and the docs linked above outline good reasons when to use them. But in general don't use them unless you know what you're doing.
An inner class is instantiated the same as any other class is, just the scope of the class (and thus its instances) is different.
So yes, your inner class instance is created by a call inside the outer class method (not the constructor in the case of your example, but the printEvent method).
I don't know what you mean with the "ds instance is created by the constructor of DataStructure". If you mean that the class is initialised by the constructor, no.
A non-static inner class is best thought of as follows (because.. they really are exactly like this, at the class level):
They have a secret (invisible) final field of the outer type's type.
All constructors, even the default (empty) one have a secret additional parameter of the same type, and they all have an additional extra syntax sugar line at the top, in the vein of this.theFinalFieldIMentionedEarlier = thatParameter;.
Calling new InnerClass() will silently pass this along as that parameter.
If no this that fits is available, you must pass the parameter yourself. However, instead of writing new InnerClass(instanceOfOuter), you write instanceOfOuter.new InnerClass() instead. The effect is identical, and at the class level, there is no difference.
Generics is rather wonky; if the outer has it, oof.
As a consequence:
Do not use non-static inner classes unless you really know what you are doing and you understand and want this weird field. If you don't, or if you feel this is confusing (and it is; most java programmers do not know this is how it works), you might want to consider making your inner class static, and making that field explicit - i.e. handrolling this functionality. It's not particularly complicated (requires 1 field, 1 constructor parameter, and 1 this.outer = outer; statement in the constructor, not exactly a boatload of boilerplate), and clears up rather a lot.
So how does it work - exactly as if it had that field. Because, that's exactly what javac does. inner classes mostly don't exist at the class level, they just become top level classes with funky names (Outer$Inner), a boatload of synthetic methods to bridge private methods together. In newer JVMs, there's the nestmates system that avoids some of those bridges, but they're still individual top-level classes after javac is done with it.
In other words, this:
class Outer {
class Inner {
public Inner(int example) {}
}
void test() {
new Inner();
}
}
is virtually identical to:
class Outer {
static class Inner {
private final Outer outer;
public Inner(Outer outer, int example) {
this.outer = outer;
}
}
void test() {
new Inner(this);
}
}
Consider the int a variables in these classes:
class Foo {
public int a = 3;
public void addFive() { a += 5; System.out.print("f "); }
}
class Bar extends Foo {
public int a = 8;
public void addFive() { this.a += 5; System.out.print("b " ); }
}
public class test {
public static void main(String [] args){
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
}
}
I understand that the method addFive() have been overridden in the child class, and in class test when the base class reference referring to child class is used to call the overridden method, the child class version of addFive is called.
But what about the public instance variable a? What happens when both base class and derived class have the same variable?
The output of the above program is
b 3
How does this happen?
There are actually two distinct public instance variables called a.
A Foo object has a Foo.a variable.
A Bar object has both Foo.a and Bar.a variables.
When you run this:
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
the addFive method is updating the Bar.a variable, and then reading the Foo.a variable. To read the Bar.a variable, you would need to do this:
System.out.println(((Bar) f).a);
The technical term for what is happening here is "hiding". Refer to the JLS section 8.3, and section 8.3.3.2 for an example.
Note that hiding also applies to static methods with the same signature.
However instance methods with the same signature are "overridden" not "hidden", and you cannot access the version of a method that is overridden from the outside. (Within the class that overrides a method, the overridden method can be called using super. However, that's the only situation where this is allowed. The reason that accessing overridden methods is generally forbidden is that it would break data abstraction.)
The recommended way to avoid the confusion of (accidental) hiding is to declare your instance variables as private and access them via getter and setter methods. There are lots of other good reasons for using getters and setters too.
It should also be noted that: 1) Exposing public variables (like a) is generally a bad idea, because it leads to weak abstraction, unwanted coupling, and other problems. 2) Intentionally declaring a 2nd public a variable in the child class is a truly awful idea.
From JLS
8.3.3.2 Example: Hiding of Instance Variables This example is similar to
that in the previous section, but uses
instance variables rather than static
variables. The code:
class Point {
int x = 2;
}
class Test extends Point {
double x = 4.7;
void printBoth() {
System.out.println(x + " " + super.x);
}
public static void main(String[] args) {
Test sample = new Test();
sample.printBoth();
System.out.println(sample.x + " " +
((Point)sample).x);
}
}
produces the output:
4.7 2
4.7 2
because the declaration of x in class
Test hides the definition of x in
class Point, so class Test does not
inherit the field x from its
superclass Point. It must be noted,
however, that while the field x of
class Point is not inherited by class
Test, it is nevertheless implemented
by instances of class Test. In other
words, every instance of class Test
contains two fields, one of type int
and one of type double. Both fields
bear the name x, but within the
declaration of class Test, the simple
name x always refers to the field
declared within class Test. Code in
instance methods of class Test may
refer to the instance variable x of
class Point as super.x.
Code that uses a field access
expression to access field x will
access the field named x in the class
indicated by the type of reference
expression. Thus, the expression
sample.x accesses a double value, the
instance variable declared in class
Test, because the type of the variable
sample is Test, but the expression
((Point)sample).x accesses an int
value, the instance variable declared
in class Point, because of the cast to
type Point.
In inheritance, a Base class object can refer to an instance of Derived class.
So this is how Foo f = new Bar(); works okay.
Now when f.addFive(); statement gets invoked it actually calls the 'addFive() method of the Derived class instance using the reference variable of the Base class. So ultimately the method of 'Bar' class gets invoked. But as you see the addFive() method of 'Bar' class just prints 'b ' and not the value of 'a'.
The next statement i.e. System.out.println(f.a) is the one that actually prints the value of a which ultimately gets appended to the previous output and so you see the final output as 'b 3'. Here the value of a used is that of 'Foo' class.
Hope this trick execution & coding is clear and you understood how you got the output as 'b 3'.
Here F is of type Foo and f variable is holding Bar object but java runtime gets the f.a from the class Foo.This is because in Java variable names are resolved using the reference type and not the object which it is referring.
I have a function multi2 which returns inner class Inner as an Object.
What happens to a - where is it saved and how can I access it?
public class C {
private static Object multi2(final int a) {
class Inner {
public int hashCode() {
return 2*a;
}
}
return new Inner(); // What happens to a?
// Who allocates a?
// Can I Access a?
}
public static void main(String[] args) {
Object o = multi2(6);
System.out.println("o.hashCode() = " + o.hashCode());
o = multi2(4);
System.out.println("o.hashCode() = " + o.hashCode());
}
}
What happens at the implementation level is that a copy of the value of a is saved in a synthetic instance variable declared in the compiled version of the C.Inner class.
The value of a is passed to the compiled Inner constructor via an extra parameter.
The C.Inner.hashCode method uses the value of the synthetic variable. Accessing a in the source code of Inner.hashCode is transformed into accessing the corresponding synthetic variable in the compiled code.
The variable in the outer scope must be final1. The synthetic variable must be final2 in the Inner class. This maintains the illusion that (potentially) multiple instances of the Inner class are seeing the same a variable. (They aren't, but since the variable(s) can't be changed, it is not possible for the code of the inner class to tell the difference.)
If you use javap to look at the bytecodes for the compiled example, you will see the mechanisms used to implement this in the outer and the inner classes.
1 - or effectively final from Java 8 onwards.
2 - If a could be mutated by an Inner method, then two Inner instances with the same outer class need to share a mutable variable whose lifetime is (now) longer than the stackframe for a multi2 call. That entails somehow turning a from stack variable into something that lives on the heap. It would be expensive and complicated.
You have defined the class Inner inside the function so the scope of the class will be
restricted with in the method. And your function is static so it will be live as long as the class definition is loaded. You have override the hashCode function inside the InnerClass so every time you are calling the multi2(param) you are creating the hashCode for the instance of InnerClass and returning the instance of the InnerClass.
So as for you questions, please correct me if i am wrong.
What happens to a ?
a is with in the scope of your static method, so it will be live as long as the class definition is loaded.
Who allocates a?
scope of a is restricted inside the static method and static method does not require instance to access it but as for the static method/variable allocation, i think it depends on JVM.
Can I Access a?
No you cannot access a from outside you static method, it is restricted with in your static method.
Since the "a" is a local parameter, you could use a different approach to read the "a" value:
public class C {
public static Object multi2(final int a) {
return new Inner(a);
}
public static void main(String[] args) {
Object o = multi2(6);
System.out.println("o.hashCode() = " + o.hashCode());
System.out.println("o.getA() = " + ((Inner) o).getA());
o = multi2(4);
System.out.println("o.hashCode() = " + o.hashCode());
System.out.println("o.getA() = " + ((Inner) o).getA());
}
}
class Inner{
public int valueA;
public Inner(int a)
{
valueA = a;
}
public int getA() {
return valueA;
}
public int hashCode() {
return 2*valueA;
}
}
I wanted to know what was actually happening, so I compiled your code and looked at the bytecode output.
Basically what happens is the compiler adds in a constructor to your class 'Inner'. It also adds a single parameter to that constructor which takes 'a'. If your multi2() method was NOT static then there would probably also be a parameter to take 'this' where 'this' is the instance of 'C' that multi2() is executing on. BUT since we're in static context, there is no 'this'.
The compiler adds a private final field to your class 'Inner' and sets that private field using the value passed via the constructor. The compiler also converts
new Inner()
into
new Inner(a)
Hashcode then accesses the private field containing the value for a.
If 'a' was an object instead of a primitive, then it would be the same way, but a reference would be passed through instead of an actual number value.
How do you access this variable? Well you access it with reflections, but there are many problems:
1) You don't know the name of the field made by the compiler, so you can only get the name by looking at the bytecode. Don't trust decompilers as they might change the name. You gotta look at the bytecode yourself to find out.
2) The compiler probably marks the field as final, which means even if you can get reflections to access the field for you, you won't be able to update it.
3) It is entirely up to the compiler to figure out field names. Field names could change between builds depending on the compiler and it's mood.
Inner is a so called local class. a is a parameter passed to the method multi2 and accessable within that scope. Outside of that method, you cannot access a.
I'am a newbie in JAVA and this came across this word called.
"A class i.e. created inside a method is called local inner class in java. If you want to invoke the methods of local inner class, you must instantiate this class inside the method".
The word in bold.
Can anyone please help me out with this one.I know it's embarrassing and i should've researched more but I just cannot understand.
Thanks.
First of all Declaring mean:
ClassName obj;
Simple meaning of instantiate is creating an object from class.
ClassName obj = new ClassName();
What is a object?
An instance of a class. From one class we can create many instances.
They are the basic runtime entities in in our program.
They may also represent user-defined data types such as lists and
vectors.
Any programming problem is analyzed in terms of objects and nature of
communication between them.
As a example:
//Define a reference(a variable) which can hold a `Person` obect.
Person p;
//Create a Person object(instantiate).
//new - use to allocate memory space for the new object
p = new Person();
What is a nested class?
A class that defined inside a class is called nested class. There 2 categories of nested classes.
inner classes
local classes
annonymous classes
Inner class:
Inner class can only be accessed by the outer class. Not by any other
class.
Inner class is a member of outer class.
Outer class can access inner class without importing.
Inner class can access any attribute or a method belong to outer
directly.
Outer class cannot access directly to a inner class.
Example for a inner class:
class Outer{
int i = 10;
void main(){
//instantiate inner class.
Inner in = new Inner();
in.show();
}
class Inner{
void show(){
System.out.print(i);
}
}
}
What is a local class?
Which are classes that are defined in a block.
Example:
public class{
int i = 10;
public main(){
class A{
void show(){
System.out.println(i);
}
}
//inside the method instantiate local class.
A obj = new obj();
obj.show();
}
//outside the main() -block(method)
//inside another method instantiate local class.
public test(){
A obj = new A();
obj.show();
}
}
To instantiate a class means to create an instance of the class. In other words, if you have a class like this:
public class Dog {
public void bark() {
System.out.println("woof");
}
}
You would instantiate it like this:
Dog myDog = new Dog();
Instantiating is when you use the new keyword to actually create an object of your class.
Instantiate == create an instance == create an object of a class.
Instantiate is creating an instance of a class. I reckon this is not helpful without knowing what an instance is.
Let's say you have a class definition like:
public class Person
{
private String name;
public Person(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
You make an instance of this class my calling its constructor and using the keyword new:
Person p = new Person("Hugh Laurie");
An instance of a class is a place in memory that contains the state (e.g., Person::name) of a given object which used as a template a class definition.
I want to further expand upon:
If you want to invoke the methods of local inner class you must instantiate this class
What this means is that, you need to have instantiated that class in order to use the above's example getName() method. After all, it is trying to access the state (name) of a given object in memory; without that object, there is no state.
Instantiate in Java means to call a constructor of a Class which creates an an instance or object, of the type of that Class. Instantiation allocates the initial memory for the object and returns a reference. An instance is required by non-static methods as they may operate on the non-static fields created by the constructor.
Static methods don't need an instance and should not be stateful, i.e. should not rely on changing data. They are essentially free functions that are associated with the type and not a particular instance. When you want to work with changing data, encapsulating that data as member fields that are operated on by instance methods is the way to go.
For example, a Car class might have static numbeOfWheels() that always returns 4, but an instance numberOfFlatTires() that might return 0-4 depending on the state of that particular Car.
Inner classes are no different and the only difference between a static and non-static inner class is that the non-static can use the parent instance's members. This can be used to reduce complexity. You might have a looping operation that has a common parameter for the list and an individual parameter for the items. You could use a non-static inner class to encapsulate the operations on the item while referring to the common parameter in the parent class.
Enums are special in that each value is a single instance of a single type that all extend from a common abstract base class defined in the Enum class body. The Enum value is instantiated the first time it's used, but there will only ever be one instance per value.
when you create an instance of a class or simply called as an object
for ex: Bike abc = new Bike();
as soon as you create this object using the new keyword, a new block of memory is created and object "abc" will now be pointing to that new block of memory, this is called as instantiation in java.
create an instance of the class by using "new" word
for example Car car = new Car();
In Java, if I have a class such as this
abstract class TestClass
{
int mMember = 0;
int getMember()
{
return mMember;
}
}
and a class that extends this class:
class TestExtended extends TestClass
{
int mMember = 1;
}
If I create an instance of TestExtended, and call testExtended.getMember(); would it return 0, or 1?
In other words, when I extend a class, and don't override a method from said class, does it call the method and act on the members in said class, or in the extended class?
Would I need to re-implement (copy-paste) the function in the extended class to get the function to return 1?
It will return 0, not 1.
This is because you cannot "override" fields from a superclass. You can set them, so long as they are not private, but if you declare a new variable with the same name, it will simply shadow the superclass variable.
On the other hand, you can override methods.
Now, shadowing member variables in this way is usually a Very Bad Idea™, and is another reason to avoid public fields. This is why:
TestExtended sub = new TestExtended();
sub.mMember = 5;
System.out.println(sub.mMember); // prints '5', as expected
TestClass sup = sub; // this is fine, TestExtended extends TestClass
System.out.println(sup.mMember); // prints '0'!
The compiler will choose which version of the variable to use based on the compile-time type, breaking polymorphism. Don't shadow member variables, and avoid public fields, and this will never matter. Use getters and setters instead.
It can be confirmed by running. It will return 0. This is because the fields cannot be overridden. What you are actually doing is hiding the instance variable as per jls.
overriding of methods differs from hiding of fields (§8.3), for it is
permissible for a field to hide a field of another type.
Check Example 8.4.8.3-4. in language specification for more info
To get the subclass version, you would have to:
class TestExtended extends TestClass
{
int mMember = 1;
#Override
int getMember(){
return mMember;
}
}
Base class methods cannot access subclass fields (at least, without using reflection). Full stop.
Also, fields do not participate in overriding, unlike methods.
Using testExtended.getMember(); obviously means you are calling the abstract class method because you dont override the method in your sub-class. if you would have overridden it then the preference would have been given to subclass method first if your object is of type subclass. so in this case it will give you 0 unless you override the method.