Can outclass specify inner class with InnerClassNameOuter directly rather than ClassName.InnerClassName - java

In Inner classes of Thinking In Java,
If you want to make an object of the inner class anywhere except from
within a non-static method of the outer class, you must specify the
type of that object as OuterClassName.InnerClassName, as seen in
main().
But I find use InnerClassName directly still works in main.
public class Parcel2 {
class Contents {
private int i = 42;
public int value() { return i; }
}
class Destination {
private String label;
Destination(String whereTo){
label = whereTo;
}
String readLabel(){ return label; }
}
public Destination to(String s){
return new Destination(s);
}
public static void main(String[] args){
Parcel2 q = new Parcel2();
/* Destionation d = q.to("Borneo"); still works.*/
Parcel2.Destination d = q.to("Borneo");
}
}

Related

How do I execute the function public method declared inside a class which is in turn inside a private method?

So, I want to execute the sum() of the following block of code:
import java.lang.reflect.Method;
public class LocalOuterClass { // start of outer
private int x = 10;
private Object run() { //start of inner
class LocalInnerClass {
private int y = 20;
public void sum() {
System.out.println(x+y);
}
} //end of inner
LocalInnerClass lc = new LocalInnerClass();
//lc.sum();
return lc;
}
public static void main(String[] args) {
LocalOuterClass Loc = new LocalOuterClass();
Object obj = Loc.run();
System.out.println(obj.getClass());
Method[] methods = obj.getClass().getMethods();
for (Method method : methods) {
String MethodName = method.getName();
System.out.println("Name of the method: "+ MethodName);
}
}
} //end of outer
When I do lc.sum(), the sum() is correctly executed. But when I'm returning an object of the inner class to the main() and try to execute sum(), it gives a compiler error. Doing getClass().getMethods() on the object does print sum() as one of the methods. What should I do to execute the sum() inside main()?
You have to change return type to LocalInnerClass and move LocalInnerClass out of the method:
public class LocalOuterClass {
private int x = 10;
private class LocalInnerClass {
private int y = 20;
public void sum() {
System.out.println(x + y);
}
}
private LocalInnerClass run() {
LocalInnerClass lc = new LocalInnerClass();
//lc.sum();
return lc;
}
public static void main(String[] args) {
LocalOuterClass Loc = new LocalOuterClass();
LocalInnerClass obj = Loc.run();
obj.sum(); // it works!
// ...
}
}
The problem is, that the whole LocalInnerClass is not known to your main-method. It does not help, that it has a public method, if the whole type is unknown. You need to refactor your code in order to change that.
Actually your method run currently returns a value of type Object and you'd need to return a value of type LocalInnerClass, however this is not possible due to type visibility.
There are basically two options you have. One is to move the whole LocalInnerClass to a location that is visible to main (like oleg.cherednik suggested):
class LocalOuterClass {
private int x = 10;
private LocalInnerClass run() { // now we can retun `LocalInnerClass`
return new LocalInnerClass();
}
public static void main(String[] args) {
new LocalOuterClass().run().sum(); // works!
}
private class LocalInnerClass {
private int y = 20;
public void sum() {
System.out.println(x+y);
}
}
}
Another option is to implement/extend a different type that has sum, e.g. like this:
class LocalOuterClass {
private int x = 10;
private Summable run() { //start of inner
class LocalInnerClass implements Summable {
private int y = 20;
public void sum() {
System.out.println(x+y);
}
}
return new LocalInnerClass();
}
public static void main(String[] args) {
new LocalOuterClass().run().sum(); // works as well
}
private interface Summable {
void sum();
}
}
With this interface-option the type LocalInnerClass is still not visible to anyone outside your run-method, however the Summable-interface is and since your LocalInnerClass implements Summable you can return a value of that type.

Java Passing variables around classes

I am new to java and am trying to pass variables like in the following example from one class to another, im wondering is this possible and how i would go about it if it is.
As this code does not work as it is not static.
Main Class
public class testAll
{
public static void main(String[] args)
{
One one = new One();
Two two = new Two();
}
}
The first class:
public class One
{
public int test = 4;
public int getTest()
{
return this.test;
}
}
The second class:
public class Two
{
public void value()
{
System.out.print("Var is: " + One.getTest());
}
}
Thanks,
Naz
Lets consider this, if you want to access a variable in Class A from Class B then Class A needs to know about Class B.
public class A {
public A(B classB){
this.classB = classB;
}
public void printValue(){
System.out.println(this.classB.getTest());
}
}
Now you will need to pass an instance of ClassB to ClassA in the constructor so that Class A has a reference to ClassB when it calls printValue();
ClassB b = new ClassB();
ClassA a = new ClassA(b);
b.getTest();
a.printValue();
You have to create an instance for class One first. Try this
public void value()
{
One one_object = new One();
System.out.print("Var is: " + one_object.getTest());
}
public class Two {
private One one;
public Two(One one) {
this.one = one;
}
public void printValue() {
System.out.print("Var is: " + one.getTest());
}
}
public class Main {
public static void main(String [] args) {
One one = new One();
Two two = new Two(one);
two.printValue();
}
}
There are two way - pass a reference or pass a value:
public class One {
private int value = 0;
public One(final int value) {
this.value = value;
}
public int getValue() { return value; }
}
public class Two {
private One one = null;
public Two(final int value) {
this.one = new One(value);
}
public Two(final One one) {
this.one = one;
}
public int getValue() { return one.getValue(); }
}
When passing a reference to a One instance, the value is read from One and will only change it the value held inside the One instance changes. When passing a primitive (int, boolean ...) the value is copied and "owned" by the Two instance. Read some more about the differences of references and values to grasp the idea. It's quite simple, once you get the idea.

Java initial values?

If I were to do something such as:
public class Game
{
private boolean RUNNING = true;
Game()
{
}
public static void main(String[] args)
{
Game game = new Game();
}
}
At what point in time would RUNNING = true?
edit: for clarity, at what point in the program would running be set to true. ex: Before the constructor, after the constructor, etc.
It will be set to true before the constructor. You can use it in the constructor as true.
This code explains itself:
public class SuperClass
{
String superField = getString("superField");
public SuperClass()
{
System.out.println("SuperClass()");
}
public static String getString(String fieldName)
{
System.out.println(fieldName + " is set");
return "";
}
public static void main(String[] args)
{
new ChildClass();
}
}
class ChildClass extends SuperClass
{
String childField = getString("childField");
public ChildClass()
{
System.out.println("ChildClass()");
}
}
OUTPUT:
superField is set
SuperClass()
childField is set
ChildClass()
When the constructor is called using the new operator all non-static members of the class are initialized before the code inside the constructor is executed. You can use the debugger and step into that call and see where it goes first. Static members are initialized when the class is loaded and for the first time accessed (see this question for more detailed info about static members).
private boolean RUNNING = true;
Game() {
}
is exactly the same as
private boolean RUNNING;
Game() {
RUNNING = true;
}
Actually, the comiler will move the initialization at the beginning of the constructor. The value will then be set when instantiating an object of that class.
When you try to use local variables which not manually initialized, you will get a compile time error.
public static void main(String args[]){
int a;
System.out.pritnln(a); //error
}
But it's not the case with instance variables. This itself shows that they are ready for usage before the constructor even.
public class Example{
private int a;
public Example(){
System.out.println(a); //No error
}
public int getA(){
return a; //No error
}
}
I hope this intuition answers your question..........

Inheritance in Java

Consider the following code in Python:
class A(object):
CLASS_ATTRIBUTE = 42
def f(self):
return "CLASS_ATTRIBUTE: %d" % self.CLASS_ATTRIBUTE
class B(A):
CLASS_ATTRIBUTE = 44
Now A().f() and B().f() return "CLASS_ATTRIBUTE: 42" and "CLASS_ATTRIBUTE: 44" respectively.
How can I achieve a similar effect in Java? I want a CLASS_ATTRIBUTE field to be initialized statically and redefined in the inherited class but the f method should be only defined in the base class.
Is there a particular reason you want the attribute to be static? In Java the typical way you'd do this is to have A contain a protected variable that you then set in the constructors of the 2 classes:
public class A
{
protected int CLASS_ATTRIBUTE;
public A()
{
CLASS_ATTRIBUTE = 42;
}
public String f()
{
return "CLASS_ATTRIBUTE: " + CLASS_ATTRIBUTE;
}
}
public class B extends A
{
public B()
{
CLASS_ATTRIBUTE = 44;
}
}
Alternatively (and probably more consistent with Java design patterns) you'd declare a function that you can override to return the value instead of using a member variable.
Short answer: you cant solve it like this in Java. You'll have to solve it in another way.
In Java you can't override or "redeclare" fields in subclasses, and you can't override static methods.
It can be solved using an ugly reflection-hack (should be avoided though):
public class Main {
public static void main(String... args) {
A a = new A();
B b = new B();
System.out.println(a.f()); // Prints 42.
System.out.println(a.fReflection()); // Prints 42.
System.out.println(b.f()); // Prints 42.
System.out.println(b.fReflection()); // Prints 44.
}
}
class A {
static int CLASS_ATTRIBUTE = 42;
public int f() {
return CLASS_ATTRIBUTE;
}
public int fReflection() {
try {
return getClass().getDeclaredField("CLASS_ATTRIBUTE").getInt(null);
} catch (Exception wontHappen) {
return -1;
}
}
}
class B extends A {
// Compiles, but will not "override" A.CLASS_ATTRIBUTE.
static int CLASS_ATTRIBUTE = 44;
}
You can't do this directly with only a variable, because in Java variables cannot override (they only shadow the super classes variables).
You need to use a protected "getter" method, which can then be overridden by the subclass:
class A
{
private int attribute=42;
...
protected int getAttribute() {
return attribute;
}
}
class B
extends A
{
private int attribute=44;
...
protected int getAttribute() {
return attribute;
}
}
But note there's a special consideration to calling methods from an object's constructor, in that it allows object code to run before object construction is complete.
I'm not sure if you meant "statically" literally or not, but here's a brief example of how inheritance at it's most basic form looks in Java. Note that using a getter method to access the variable is a better idea for several reasons -- this is just an example.
public class Dog {
protected String whatISay = "Woof!";
public void speak(){
System.out.println(whatISay);
}
}
public class Poodle extends Dog {
public Poodle(){
whatISay = "Yap!";
}
}
public class Main {
public static void main(String[] args){
Poodle fluffy = new Poodle();
fluffy.speak();
Dog dog = new Dog();
dog.speak();
}
}
Yap!
Woof!
This way of doing it introduces as little intrusion as I could think of. setAttribute() could be named something like setDefaultValue() if that's clearer.
public class A
{
protected int attribute;
public A()
{
setAttribute();
}
public String f()
{
return "CLASS_ATTRIBUTE: " + attribute;
}
protected void setAttribute()
{
attribute = 42;
}
}
public class B extends A
{
#Override
protected void setAttribute()
{
attribute = 44;
}
}
public class Main
{
public static void main(String[] args)
{
A a = new A();
B b = new B();
System.out.println("A: " + a.f());
System.out.println("B: " + b.f());
}
}

Don’t call subclass methods from a superclass constructor

Consider the following code
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package example0;
/**
*
* #author yccheok
*/
public class Main {
static class A {
private final String var;
public A() {
var = getVar();
// Null Pointer Exception.
System.out.println("var string length is " + var.length());
}
public String getVar() {
return "String from A";
}
}
static class B extends A {
private final String bString;
// Before B ever constructed, A constructor will be called.
// A is invoking a overriden getVar, which is trying to return
// an initialized bString.
public B() {
bString = "String from B";
}
#Override
public String getVar() {
return bString;
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
B b = new B();
}
}
Currently, in my mind, there are two ways to avoid such problem.
Either making class A final class.
static final class A {
private final String var;
public A() {
var = getVar();
// Null Pointer Exception.
System.out.println("var string length is " + var.length());
}
public String getVar() {
return "String from A";
}
}
Or
Making getVar method final
static class A {
private final String var;
public A() {
var = getVar();
// Null Pointer Exception.
System.out.println("var string length is " + var.length());
}
public final String getVar() {
return "String from A";
}
}
The author trying to suggest ways to prevent the above problem. However, the solution seems cumbersome as there are some rules to be followed.
http://benpryor.com/blog/2008/01/02/dont-call-subclass-methods-from-a-superclass-constructor/
Beside making final and the author suggested way, is there more ways to prevent the above problem (Don’t call subclass methods from a superclass constructor) from happen?
Making getVar method final
This is definitely what you need to do.
If you're relaying on the functionality of a method to initialize an object, you shouldn't let subclasses broke that method.
Answering your question, other way to prevent it is to make getVar private in A.
See this simplified version of your code:
// A.java
class A {
private final String var;
public A(){
var = getVar();
var.length();
}
private String getVar(){
return "This is the value";
}
}
class B extends A {
private final String other;
public B(){
other = "Other string";
}
public String getVar(){
return other;
}
}
class Main{
public static void main( String [] args ) {
new B();
}
}
BTW, why did you put those as static nested classes, just to create confusion?

Categories

Resources