inner class problem~

my test code can not work properly, the matter is compiler forbid me from creating instances of the inner class within main method, how to fix it pls ?


public class TestThread
{
      public static void main(String[] args)
      {
            MyThread thread1 = new MyThread("black", 5);
            MyThread thread2 = new MyThread("white", 3);
            thread1.start();
            thread2.start();
      }

      private class MyThread extends Thread
      {
            public MyThread(String name, int num)
            {
                  this.name = name;
                  this.num = num;
            }

            public void run()
            {
                  for (int i=0; i<num; i++)
                  {
                        try
                        {
                              sleep((long)100);
                        }
                        catch (Exception e) {};
                        System.out.println(name + "\trunning: " + i);
                  }
            }

            private String name;
            private int num;
            public int xxx = 5;
      }
}

regards~

and here is the output looks like:

TestThread.java:7: non-static variable this cannot be referenced from a static context
MyThread thread1 = new MyThread(“black”, 5);
^
TestThread.java:8: non-static variable this cannot be referenced from a static context
MyThread thread2 = new MyThread(“white”, 3);
^
2 errors
Output completed (0 sec consumed) - Normal Termination

anyone could figure it out… tks !

All inner (private) classes require an outer (public) class when created because they have an implicit ‘this’ pointer to the outer object. So you can only really create instances of inner classes from an object of the outer class.

Ditch MyThread and move all its methods into TestThread, then just create an instance of that in main().

[quote]All inner (private) classes require an outer (public) class when created because they have an implicit ‘this’ pointer to the outer object. So you can only really create instances of inner classes from an object of the outer class.

Ditch MyThread and move all its methods into TestThread, then just create an instance of that in main().
[/quote]
u mean to put inner class within the constructor ? i tried but it does not work yet, compiler just reports this:

---------- Java compiler ----------
TestThread1.java:7: illegal start of expression
private class MyThread extends Thread
^
TestThread1.java:7: ‘;’ expected
private class MyThread extends Thread
^
2 errors
Output completed (1 sec consumed) - Normal Termination

what’s the problem here ?

what OrangyTang was suggesting was having TestThreas extend thread, and putting all the methods from ‘MyThread’ into TestThread then instantiating a couple of instances of ‘TestThread’ from your main method.

IE:


public class TestThread extends thread
{
    public static void main(String[] args)
    {
        TestThread thread1 = new TestThread("black", 5);
        TestThread thread2 = new TestThread("white", 3);
        thread1.start();
        thread2.start();
    }
 
     public TestThread(String name, int num)
     {
          this.name = name;
          this.num = num;
     }
 
     public void run()
     {
          for (int i=0; i<num; i++)
          {
               try
               {
                    sleep((long)100);
               }
               catch (Exception e) {};
               System.out.println(name + "\trunning: " + i);
          }
     } 
     private String name;
     private int num;
     public int xxx = 5;
}


Quite apart from the fact that it doesn’t work as written, Theres really no need to have the inner classes at all. IF you want to still use your inner class then you’ll have to supply a constructor for TestThread which instantiates and runs a couple of instances of MyThread then in the Main method, instanciate and run an instance of TestThread.

D.

[quote] TestThread.java:7: non-static variable this cannot be referenced from a static context
[/quote]
Simplest solution, make your inner class static.

tks guys and i already find another different solution, just remove main method in TestThread class and put initialization code inside it’s constructor, then create another class named say, Test, and build instance of TestThread within Test’s main method, it really works, ha!

to gamehacer2000: make it static seems a wonderful trick, i’d like to try it out, and this is the first time i got inner class can be implemented static :stuck_out_tongue:

Another hack…

You can also put MyThread outside the scope of TestThread, making it a package class.

public class TestThread
{
public static void main(String[] args)
{
MyThread thread1 = new MyThread(“black”, 5);
MyThread thread2 = new MyThread(“white”, 3);
thread1.start();
thread2.start();
}
} // enf of TestThread
class MyThread { // begining of package classes

}

Lilian

BlackJava, you should read this http://www.javaranch.com/campfire/StoryInner.jsp

No Statics!! :slight_smile:

I don’t really use inner classes nor do I care to. However, you should know all options when you are programming including “top-level nested classes.” Considering how little the inner class is dependent on the inner class except for the main method, there is no need to instatiate an instance of both the outer and inner class. In this case, it is better just to make the class a nested class. Although, in this case it would be best just to have the outer class implement Runnable, supply an instance to the Thread constructor, and get rid of the inner class altogether.



public class TestThread implements Runnable
{
    private int num;
    private String name;

    public  TestThread(String name, int num)
    {
          this.name = name;
          this.num = num;
    }

    public void run()
    {
          for (int i=0; i<num; i++)
        {
              try
            {
                  Thread.currentThread().sleep((long)100);
            }
            catch (Exception e) {};
            System.out.println(name + "\trunning: " +    i);
        } 
    }
 
    public void main(String[] args)
    {
          Thread t1 = new Thread(new TestThread("black",5));
             Thread t2 = new Thread(new TestThread("white",3));
          t1.start();
          t2.start();
    }
}
 

However, I see that blackjava is just using the class to test inner classes so best practices aren’t necessarily applicable.

inner classes is the most pointless and bug-prone feature in Java (and is usually used by newbies to “easily” access the containing class’ variables :-/). You’d be better off by just using two seperate classes…

[quote]inner classes is the most pointless and bug-prone feature in Java (and is usually used by newbies to “easily” access the containing class’ variables :-/). You’d be better off by just using two seperate classes…
[/quote]
Care to justify any of that rant?

I tend to disagree. Inner classes are quite useful and I have never seen any evidence that they are “bug-prone”. Sure you can find ways to work without them, but what do you gain?

yeah - Inner classes are rather usefull!
Think of a List and a ListItem which need to cooperate tightly.

Agreed - I also think they are an essential part of Java. I can see no justification for those comments.

And far from being a “newbie” tool, I get the impression that the syntax is sufficiently alien-looking to someone who doesn’t understand them that they are very much an advanced part of the language. New users will not use them lightly, expert users can be trusted to use them correctly.

public class Wheee
{
  private class Foo
  {
    private String msg = "Inner classes are fun!";
  }

  private class Bar extends Foo
  {
    private String msg = ".. but confusing unless you've studied the JLS.";
  }

  public void test()
  {
    Foo bar = new Bar();
    System.out.println(bar.msg);
    System.out.println(((Bar)bar).msg);
  }
}

output:

Inner classes are fun!
.. but confusing unless you've studied the JLS.

There is some justification for describing inner classes as bug prone — they gave rise to numerous bugs in javac. There are still a few issues with the implementation of inner classes, notably with regard to access permissions and reflection.

[quote]inner classes is the most pointless and bug-prone feature in Java (and is usually used by newbies to “easily” access the containing class’ variables :-/). You’d be better off by just using two seperate classes…
[/quote]
There are so many things wrong with this statement that I don’t know what to say.

Vorax, it sounds to me you literally dont know what to say and are just jumping on the hate wagon. At least the others who disagreed has the intelligence to include a point of argument…

I do have some justification for the comment I made.

I think it is a bad design to do something like:


public class Blah {
      class Whatever {
            // ...
      }
}

that looks very non-OO to me (not to mention it leaves ugly class files such as Blah$Whatever.class, but that’s inevitable anyway). Better design would be to create two seperate classes. I do, however, find this type of inner class useful:


public class Blah extends Frame {
      public Blah() {
            addWindowListener(new WindowAdapter() {
                  public void windowClosing(WindowEvent e) {
                        System.exit(0);
                  }
            });
      }
}

that is much more convenient than creating an entirely different class just for window event handling. My opinion is if the class has some serious processing to do (other than simple things like event handling) then it needs to be a seperate class entirely.

call me an OO conformist if you want, you can take the same argument to the same people who want switch/case to be shot.

[quote]There is some justification for describing inner classes as bug prone — they gave rise to numerous bugs in javac. There are still a few issues with the implementation of inner classes, notably with regard to access permissions and reflection.
[/quote]
touché :slight_smile:

[quote] Vorax, it sounds to me you literally dont know what to say and are just jumping on the hate wagon. At least the others who disagreed has the intelligence to include a point of argument…
[/quote]
I didn’t read the other posts when I replied to yours.

So…let me elaborate:

[quote]inner classes is the most pointless and bug-prone feature in Java
[/quote]
They are far from pointless and useful for things like:

  • Implementing listeners (as you did)
  • Implementing visitors
  • Implementing traversal handlers
  • Implementing runnables to spawn one shot threads
  • Implementing data objects
  • Much more…

As for bugs: In 9 years of Java programming I have seen very few (I can’t even recall any) bugs caused due to the use of inner classes.

There are lots of ways to make bugs, but inner classes, unless you are have no idea how to use them, are no more error prone then anything else in the language and less so then many other key features. For example, casting, subclassing and scope all cause FAR more bugs then inner classes. Cast to the wrong type, overload a parents incorrectly scoped variable or method, misrepresent the functionality of a method are all much more common problems…maybe we should all be using C?

Most Java newbies have no idea about inner classes and even fewer know you can use them to access the parents members.

[quote] You’d be better off by just using two seperate classes…
[/quote]
But what if you don’t want the second class to be represented in the package because it has no meaning except to the class that uses it? That is the point of inner classes: Cleaner API’s and packages and REDUCED errors from exposing classes that shouldn’t be used by others.

Should I do this:

public interface CallBackThing {
public void callBack();
}

public class Test {
public Test() {

callsBackThings.add( new CBHandler() ) ;
}
}

public CBHandler implements CallBackThing {
public void callBack() {
System.out.println("I was called back on behalf of “Test”);
}
}

…What if someone now instantiates and uses CBHandler? It is useless to them and is cluttering up the API. It is specific to Test and means nothing to anything else…picture there are dozens of classes like Test, should their be dozens of CBHandler type classes? What if we want to implement several interfaces, should Test be forced to implement all of them even if they make no sense to the class thus corrupting its purpose and causing it to loose functional decomposition? What if you don’t want Test to be used as one of the interfaces it is exposing? Since it implemented it, there is nothing stopping someone from doing so. If it implemented CallBackThing, it has no control and could be added by somone else to something that takes a CallBackThing as a parameter…more bugs.

In Java, the inner class way is better:

public class Test {
public Test() {
callsBackStuff.add( new CBHandler(this) ) ;
}

CBHandler implements CallBackThing {
public void callBack() {
System.out.println(“I was called back on behalf of Test”);
}
}
}

Now no one using Test has to be concerned with it’s internal working which means it has better encapsulation (also no one can cast it to anything other then its type, purposefully implemented interfaces or Object), a key goal of OOP. The same goes for the inner class, even it’s type has no meaning outside the parent class so it can not be used incorrectly when passed by it’s interface. Inner classes aren’'t unobject oriented, they are VERY object oriented.

Inner classes alllow more complete encapsulation while at the same time preventing packages from being cluttered with .java files that have no meaning and should never be used outside the class they were built for…if they can be used outside that class, then they should be public and become first class citizens of the package.

This is how I see and use inner classes and it’s why I had such a problem with your statment.

Edit: My lack of a reply had nothing to do with my intelligence, but thanks for the jab. I didn’t reply because I have beeing doing OOP since 1987 and have been explaining things like this for almost 20 years and am tired of doing it. To me your remarks seemed like that of a newbie, not of someone with a point and I have yet to see one from you that justifies your stance.