I have the following piece of code:
public class MyClass {
class Inner {
int s, e, p;
}
public static void main(String args[]) {
Inner in;
}
}
Up to this part the code is fine, but I am not able to instantiate 'in' within the main method like in = new Inner() as it is showing non static field cannot be referenced in static context.
What is the way I can do it? I do not want to make my Inner class static.
You have to have a reference to the other outer class as well.
Inner inner = new MyClass().new Inner();
If Inner was static then it would be
Inner inner = new MyClass.Inner();
A "regular" inner class has a hidden (implicit) pointer to a Outer class instance. This allows the compiler to generate the code to chase the pointer for you without you having to type it. For instance, if there is a variable "a" in the outer class then the code in your inner class can just do "a=0", but the compiler will generate code for "outerPointer.a=0" maintaining the hidden pointer under the covers.
This means when you create an instance of an inner class you have to have an instance of a outer class to link it to. If you do this creation inside a method of the outer class then the compiler knows to use "this" as the implicit pointer. If you want to link to some other outer instance then you use a special "new" syntax (see code snippet below).
If you make your inner class "static" then there is no hidden pointer and your inner class cannot reference members of the outer class. A static inner class is identical to a regular class, but its name is scoped inside the parent.
Here is a snippet of code that demonstrates the syntax for creating static and non-static inner classes:
public class MyClass {
int a,b,c; // Some members for MyClass
static class InnerOne {
int s,e,p;
void clearA() {
//a = 0; Can't do this ... no outer pointer
}
}
class InnerTwo {
//MyClass parentPointer; Hidden pointer to outer instance
void clearA() {
a = 0;
//outerPointer.a = 0 The compiler generates this code
}
}
void myClassMember() {
// The compiler knows that "this" is the outer reference to give
// to the new "two" instance.
InnerTwo two = new InnerTwo(); //same as this.new InnerTwo()
}
public static void main(String args[]) {
MyClass outer = new MyClass();
InnerTwo x = outer.new InnerTwo(); // Have to set the hidden pointer
InnerOne y = new InnerOne(); // a "static" inner has no hidden pointer
InnerOne z = new MyClass.InnerOne(); // In other classes you have to spell out the scope
}
}
If you want to create new Inner() from within a method, do it from an instance method of the class MyClass:
public void main(){
Inner inner = new Inner();
}
public static void main(String args[]){
new MyClass().main();
}
Alexei Kaigorodov's is the right answer. His solution allows you to instantiate inner classes from within a static method, such as a main() of the same class. Otherwise, you can't instantiate an inner class within a static method. It does not compile. Alexei's solution does compile and it does allow you to instantiate inner classes from a static method. The other answers are interesting side-notes, but I don't find them responsive to the actual question.
import java.awt.Graphics;
import java.awt.Color;
import javax.swing.JPanel;
import javax.swing.JFrame;
public class Example {
public class InnerClass extends JPanel {
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(getX(),getY(),getWidth(),getHeight());
g.setColor(Color.RED);
g.fillRect(5, 20, 195, 20);
g.setColor(Color.BLACK);
g.drawString("This was written by an inner class.", 10, 35);
}
}
public void demonstrate() {
InnerClass sc = new InnerClass();//<---this is key
JFrame jf = new JFrame();
jf.add(sc);
jf.setSize(220, 130);
jf.setLocation(450, 450);
jf.show();
}
public static void main(String[] params) {
Example e = new Example();//<---so is this
e.demonstrate();//<---and this is also key
}
}
Related
Can a innerclass also be a subclass. Also one more thing in this set of java planguage it's not allowing me to create a instance of subclass even though I already created a instance of my encapsulating class for the innerclass.
public class Main {
Main OpTypes[] = new Main[3];
public static void main(String[] args) {
Main c = new Main();
c.OpTypes[0] = new Division(6,3);
Jool x = new Jool();
}
public class Jool {
public Jool() {
}
}
}
If you try it, you'll find that an inner class can extend a class.
Also, since the inner class is not static, it requires an instance of the outer class when constructing it. In the code below, you'll see two ways of doing that.
Method test shows the most common way, which is to do it from an instance (non-static) method of the outer class, in which case the outer class is implicit.
Method main shows how to do it outside of an instance method of the outer class, in which case you have to give an outer class instance before the new operator.
class MyBaseClass {
}
class Main {
public static void main(String[] args) {
Main c = new Main();
Jool x = c.new Jool(); // "c" explicitly used as outer class instance
}
public void test() {
Jool x = new Jool(); // "this" implicitly used as outer class instance
}
public class Jool extends MyBaseClass { // Inner class extends unrelated class
}
}
class Outer
{
int x=10;
class Inner
{
void show()
{
System.out.println(x);
}
}
public static void main(String args[])
{
Outer obj=new Outer();
Inner obj1=new Outer().new Inner();
obj1.show();
}
}
I tried making a non static nested class and tried to use non static data member of outer class in non static inner class. I did not get that if x is non static, how i am using it without object. Kindly give me the answer?
You're not using it without an object. Inner (non-static nested) classes have a reference to the outer object, whose x is used.
Inner class is just a syntactic sugar to have an implicit reference to an outer class. Internally (after javac compilation) your class Inner looks like this:
static class Inner
{
private final Outer this$0;
public Inner(Outer outer) {
this$0 = outer;
}
void show()
{
System.out.println(this$0.x);
}
}
And when you write Inner obj1=new Outer().new Inner(); the compiler changes it to something like Inner obj1=new Inner(new Outer());.
If I have an inner class e.g.
class Outer{
class Inner{}
}
Is there any way to check if an arbitrary Object is an instance of any Inner, regardless of its outer object? instanceof gives false when the objects are not Inners from the same Outer. I know a workaround is just to make Inner a static class, but I'm wondering if what I'm asking is possible.
Example:
class Outer{
Inner inner = new Inner();
class Inner{}
public boolean isInner(Object o){
return o instanceof Inner;
}
}
Outer outer1 = new Outer();
Outer outer2 = new Outer();
boolean answer = outer1.isInner(outer2.inner); //gives false
And what about?
public static boolean isInnerClass(Class<?> clazz) {
return clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers());
}
The method isMemberClass() will test if the method is a member (and not an anonymous or local class) and the second condition will verify that your member class is not static.
By the way, the documentation explains the differences between local, anonymous and nested classes.
Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are simply called static nested classes. Non-static nested classes are called inner classes.
o instanceof Outer.Inner gives false when o is an instance of an Inner of any Outer other than the one you're calling it from.
This doesn't happen for me - I get true for o instanceof Inner regardless of which particular enclosing instance of Outer the o belongs to:
class Outer {
class Inner {}
void test() {
// Inner instance that belongs to this Outer
Inner thisInner = new Inner();
// Inner instance that belongs to a different Outer
Outer other = new Outer();
Inner otherInner = other.new Inner();
// both print true
System.out.println(thisInner instanceof Inner);
System.out.println(otherInner instanceof Inner);
}
public static void main(String[] args) {
new Outer().test();
}
}
Tested with both Java 6 and 7.
Did you try using getEnclosingClass():
Returns the immediately enclosing class of the underlying class. If the underlying class is a top level class this method returns null.
Outer.class.equals(object.getClass().getEnclosingClass())
Getting the correct enclosing class of the object , IMHO is not so easy . Read this.
Somewhat of a hack would be :
object.getClass().getName().contains("Outer$");
you could always:
getClass().getName()
and do a String comparison.
EDIT : to account for inheritance (among inner classes? who would do that?!) you could always loop through getSuperclass() and check for them as well, and even go after implemented interfaces.
The java.lang.Class.getEnclosingClass() method returns the immediately enclosing class of the underlying class. If this class is a top level class this method returns null.
The following example shows the usage of java.lang.Class.getEnclosingClass() method:
import java.lang.*;
public class ClassDemo {
// constructor
public ClassDemo() {
// class Outer as inner class for class ClassDemo
class Outer {
public void show() {
// inner class of Class Outer
class Inner {
public void show() {
System.out.print(getClass().getName() + " inner in...");
System.out.println(getClass().getEnclosingClass());
}
}
System.out.print(getClass().getName() + " inner in...");
System.out.println(getClass().getEnclosingClass());
// inner class show() function
Inner i = new Inner();
i.show();
}
}
// outer class show() function
Outer o = new Outer();
o.show();
}
public static void main(String[] args) {
ClassDemo cls = new ClassDemo();
}
}
Output
ClassDemo$1Outer inner in...class ClassDemo
ClassDemo$1Outer$1Inner inner in...class ClassDemo$1Outer
I was googling for finding out better answers, to find out that there are none out there.
Here is what I have which works pretty well:
public static boolean isStatic(Class klass) {
return Modifier.isStatic(klass.getModifiers());
}
/**
* Non static inner class
*/
public static boolean isInnerclass(Class klass) {
return klass.getDeclaringClass() != null && !isStatic(klass);
}
Will return true for local inner classes. isMemberClass and others do not work for this purpose.
i followed the link http://developer.android.com/reference/android/app/AlertDialog.html and i try to create new AlertDialog like this
AlertDialog myAlertDialog = new AlertDialog.Builder(MainActivity.this).create();
as per the document AlerDialog is the outerclass and Builder is the inner class within AlertDialog. Now i linked the same concept with java in accessing the inner class like this Outer myOuter2 = new Outer.Inner(); this piece of gives error when i try to access, here is the complete java code
package com.test;
public class Outer {
public void OuterMethod() {
System.out.println("OuterMethod");
}
public static void main(String[] args) {
Outer myOuter = new Outer();
myOuter.OuterMethod();
Outer myOuter2 = new Outer.Inner();//this piece of code gives error
}
class Inner {
Inner() {
System.out.println("constructor Inner");
}
public void InnerMethod() {
System.out.println("Inside InnerMethod");
}
}
}
so my question over here is how to understand the same inner class concept in android and accessing the methods within that
You have created an inner non-static class (an inner instance class), whereas AlertDialog.Builder is a static class.
To get your code to work as is you need an interesting way of invoking new that goes like this:
Outer.Inner myOuter2 = myOuter.new Inner();
This is because it acts much like any other non-static field within Outer - it requires an instance of Outer in order to be valid. In any event, this is often not a good idea as public inner non-static classes are rare.
More likely you want Inner to be a static class, i.e. one declared as:
static class Inner {
Essentially this decouples Inner from its containing class, it just happens to live inside it and so can be instantiated via new Outer.Inner(). It could happily live as a public class in its own right in a new .java file instead.
Inner static classes are useful when the inner class is only used in relation the outer class, so it shows the relationship between them.
In Android's case you use an AlertDialog.Builder only when building an AlertDialog. If it was a general Builder used by other classes (e.g. a plain Dialog) is would have instead been declared as its own public class (i.e. a standalone class that is not nested inside another).
There is no relationship between Outer and Inner except that they share a class file. Hence, you cannot type:
Outer myOuter2 = new Outer.Inner();
Perhaps you meant:
Outer.Inner myInner = new Outer.Inner();
The Inner class will need to be declared as static for this to work.
Note that a normal builder will return a type that is equal to the enclosing type. Here's a small example using similar class names to your code:
public class Outer {
public static void main(String[] args) {
Outer outer = new Outer.Builder().withParam("foo").build();
}
private final String someParam;
private Outer(String someParam) {
this.someParam = someParam;
}
public static class Builder {
private String someParam;
public Builder() {
}
public Builder withParam(String value) {
this.someParam = value;
return this;
}
public Outer build() {
return new Outer(someParam);
}
}
}
You may also wish to read Item #2 of Joshua Bloch's Effective Java, 2nd Edition for a good description of builder design and rationale. Available online: here.
Your inner class is non static type.
We should first create instance of your outer class:
Outer o=new Outer();
Outer.Inner oi=o.new Inner();
This is the basic way of create non static inner class object.
Suppose if your inner is of type static (i.e. static class Inner{....}),
then for creating object:
Outer.Inner oi=new Outer.inner();
The AlertDialog.Builder class is a static inner class as you can see here.
public static class Builder {...}
Finally i figured out here is the code
package com.test;
public class Outer {
public void OuterMethod() {
System.out.println("OuterMethod");
}
public static void main(String[] args) {
Outer myOuter = new Outer();
myOuter.OuterMethod();
Outer myOuter2 = new Outer.Inner().InnerMethod();
}
static class Inner {
Inner() {
System.out.println("constructor Inner");
}
public Outer InnerMethod() {
Outer myOuter = new Outer();
System.out.println("Inside InnerMethod");
return myOuter;
}
}
}
Is it possible for the nested inner classes ABar and BBar to access main class's variables? For example:
public class Foo {
public ABar abar = new ABar();
public BBar bbar = new BBar();
public int someCounter = 0;
public class ABar {
public int i = 0;
public void someMethod(){
i++;
someCounter++;
}
}
public class BBar {
public void anotherMethod(){
bbar.someMethod();
someCounter++;
}
}
}
// then called using: //
Foo myFoo = new Foo();
myFoo.bbar.anotherMethod();
Edit
Seems the code I typed would have worked if i'd have tried it first; was trying to get help without being too specific. The code I'm actually having trouble with
Fails because of the error 'cannot make static reference to the non-static field stage'
public class Engine {
public Stage stage = new Stage();
// ...
public class Renderer implements GLSurfaceView.Renderer {
// ...
#Override
public void onDrawFrame(GL10 gl) {
stage.alpha++;
}
}
public class Stage extends MovieClip {
public float alpha = 0f;
}
In your code, yes, it is possible.
Non-static nested classes (inner classes) have access to other members
of the enclosing class, even if they are declared private. Static
nested classes do not have access to other members of the enclosing
class.
See: Nested Classes
If your inner class extends the outer class, then it will have access to the outer class public and protected members. I just tired it and it worked. The construct is a bit odd, because it implies a sort of infinite loop in the class definition, but it seems to do the job.