I've been programming for years using .NET and I'm taking the plunge into Java with some simple starter programs.
I'm having a bit of trouble though...
When I create my start-up class with public void main, the compiler won't let me instantiate any of the classes I've written?
The error I'm getting is "non-static variable _processor cannot be referenced from a static context" where _processor is the object I'm trying to instantiate from the Processor class that I wrote.
The program will compile and run just fine when I change Processor to a static class, but I don't want to have to make all of my classes static.
Any way around this?
Thanks in advance!
Here's everything I've written. It won't compile in the current state:
class Lab
{
public static void main(String[] args)
{
Processor proc = new Processor();
proc.Go();
}
private class Processor
{
private Random _rand = new Random();
public void Processor() {}
public void Go()
{
}
}
}
Is Processor an inner class of Lab by any chance? (yes, now that you published your code, my suspicion is confirmed).
In Java, nonstatic inner classes contain an implicit reference to the containing object of the outer class, so they can't be instantiated from static context (from your main method).
So
either create an instance of Lab (e.g. myLab), and then call myLab.new Processor(), or
declare Processor static (as you did), or
turn Processor into a top level class.
Is this your problem, by any chance?
public class DemoClass{
String field;
public static void main(String[] args){
field = "Hey"; //forbidden - can't access instance field from static context
DemoClass dc = new DemoClass();
dc.field = "Hey"; //this is ok
}
}
You should call a constructor from main:
public static void main(String[] args){
new MyClass();
}
And put your instantiations in the constructor.
but I don't want to have to make all of my classes static.
Most inner classes in Java are static, in my experience. If you can write an inner class in a separate file (it does not use directly the members of the containing class), it should then be defined as static. It really is only for convenience that Java lets you write inner static classes inside other classes.
Your process class is an inner class of your lab class, you can't create an instance of your process class until you instantiate an instance of you lab class, unless that inner class is static or something.
Main will run in your lab class, because it is static, but when you attempt to create an instance of the private inner class, you can't because this class is a "private inner" class of Lab, and you don't have a lab instance, so you can't reference it directly.
You can try making your processor class static, or at the very least public, or better yet you can instantiate an instance of your lab class first, and reference creation of the processor class through your instantiate lab class.
Related
Java initializes outer class static field when that class is interacted with, but does not initialize nested static class field.
So I have read the nested class documentation: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html and I think it comes down to this line here:
In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.
If my understanding is correct that means that java views my two classes below as separate entities;
public class OutterClass {
private static final OutterClass outterField = new OutterClass("outterField");
private OutterClass(String string) {
System.out.println(string + " has been initialised");
}
private static class InnerClass {
private static final OutterClass innerField = new OutterClass("innerField");
}
public static void foo() {}
}
Meaning that when I interact with the OuterClass by calling the Outer.foo(), java will initialize my static field as it is part of the OuterClass. But since it views the InnerClass as a separate top level class, InnerClass's fields don't get initialized.
1) Is my understanding correct?
2) Has this got anything to do with the JIT compiler or the class loader? Is the InnerClass loaded when the OuterClass is loaded?
Thanks
1) Is my understanding correct?
Basically yes. Consider what happens with your static member outerField :
public class OutterClass {
private static final OutterClass outterField = new OutterClass("outterField");
Theoretically, it's possible that the JVM could create that static final object when the program starts running, or when the class is loaded, but it doesn't. Instead, it'll only initialise it when needed - basically :
Instance of class is created, or
One of the Class's static fields or methods is accessed
(see https://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1 )
So also with the static inner class. As you say, the JVM regards it as a top level inner class, so will only initialise its members when it also is needed.
2) Has this got anything to do with the JIT compiler or the class loader?
No and no. Initialisation of static members does not take place at class load time, but later (as we said, when the class is accessed). This is not a matter of compiler optimisation, but explicitly specified behaviour. After all, when you load a possibly-large class library, you would not want your JVM to consume memory or time initialising all the static members of classes that your program never touches; only-on-demand is a much better approach.
Is the InnerClass loaded when the OuterClass is loaded?
Yes (but not initialised then)
I'm reading 'Thinking of Java' and I have encountered some weird example (for me)
class StaticTest {
static class StaticClass {
int i = 5;
}
}
public class I {
public static void main(String[] args) {
// TODO Auto-generated method stub
StaticTest.StaticClass t = new StaticTest.StaticClass();
}
}
How is it possible to create instance of static class? Is it some exception to the rule 'You can't create instance of static class'?
Thanks in advance
In case of classes, the modifier static describes the relationship between the outer and the inner class.
If the inner class is not static, it is bound to an instance of the outer class and threrefore cannot be created from outside.
A static inner class can completely be created without an instance of the outer class, but has privileged access to members of the class.
A static class is nothing more than a class, but with the difference to where it's code is placed.
Therefore, you can create instances of static classes. The only difference is you have to provide the name of the class, which nests the static one (as shown on your code snippet).
StaticTest.StaticClass t = new StaticTest.StaticClass();
From Java docs regarding creating instance for static nested classes.
And like static class methods, a static nested class cannot refer directly to instance
variables or methods defined in its enclosing class — it can use them only through an
object reference.
For example, to create an object for the static nested class, use this syntax:
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
in this case static describes the relation b/w inner and outer class
it doesnt mean the inner class is static
a static nested class doesnt invoke non-static methodes or access non-static fields of an instance of class within which it is nested
As I have recently started programming, I was a little stuck in this area of coding.
There is a programming lesson named nested classes. But when I want to use it, it actually does not do what the homework wants. Here is an example of what I need to achieve:
public class Zoo {
...
public static class monkey {
...
}
}
and in the main
Zoo zoo1 = new Zoo();
...
zoo1.monkey.setage(int);
...
But there is a problem here that whenever I want to call monkey from zoo1, the debugger says that it's not possible.(Remember that I want to do this without creating an instance of monkey)
Thanks in advance
Update: I am just wondering if it's a kinda language limitation, then how the oracle itself could do that rather easily with system.out.printf?
You can not access the monkey class via an instance of Zoo, it would not actually make any sense to do that. If you want to access static methods of monkey from the main you can just use the example below
public class Zoo {
public static void main(String[] args) {
// Example 1
monkey.setage(3);
// Example 2
Zoo.monkey.setage(3);
}
public static class monkey {
private static int age;
public static void setage(int age) {
monkey.age = age;
}
}
}
But what are you actually trying to accomplish?
monkey looks static to me. They should be public instead of Public, though.
I would say that setage() is not a static method. If that's the case, and if age is a property of a monkey, than it wouldn't make sense to call it statically -- whose age would you be setting?
The problem though is that you can't seem to be able to access the static inner class through a variable of the outer class type.
So it should be Zoo.monkey instead of zoo1.monkey.
If you just want to control scoping or naming, you can use packages.
For example, you could have the following:
package com.example.application.feature;
public class MyClass {
public void f() {
System.out.println("Hello");
}
}
in a source file called com/example/application/feature/MyClass.java.
Edit: I didn't see you note "(Remember that I want to do this without creating an instance of monkey)"
sometimes before asking, searching might help you to save some time.Direct Quotion from this address: http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
Inner Classes
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. Also, because an inner class is
associated with an instance, it cannot define any static members
itself.
Objects that are instances of an inner class exist within an instance
of the outer class. Consider the following classes:
class OuterClass {
...
class InnerClass {
...
} }
An instance of InnerClass can exist only within an instance of
OuterClass and has direct access to the methods and fields of its
enclosing instance. The next figure illustrates this idea.
An Instance of InnerClass Exists Within an Instance of OuterClass
To instantiate an inner class, you must first instantiate the outer
class. Then, create the inner object within the outer object with this
syntax:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
Additionally, there are two special kinds of inner classes: local
classes and anonymous classes (also called anonymous inner classes).
Both of these will be discussed briefly in the next section.
I was helping a friend on his Java homework today, and I guess I didn't realize there being a difference between plain Java and Java in Android. Quick write up of the program:
public class myClass{
public static void Main (String[] args){
doThis();
}
public void doThis(){
System.out.println("Did this");
}
}
But when running that, I got a complaint that I needed to make the doThis() method to be static. Why is that? When I develop some basic things in Android, I never have to use the static keyword.
Note: This could stem from the fact that I'm intimidated by what static actually means.
Why is that?
Because Main() is static.
If Main() was an instance method, and you had called Main() on an instance of myClass (e.g., new myClass), then doThis() could also be an instance method. Or, if your static Main() created an instance of myClass, it could call doThis() on that instance.
When I develop some basic things in Android, I never have to use the static keyword.
That is because your entry points in Android tend to be instance methods on components (e.g., onCreate() of an Activity.
A static method is a method that is not invoked on any Object instance. A non-static method belongs to an object, and needs an object instance in order to be invoked. It's thus not legal to call an instance method from static method, since the static method is not invoked on any object.
You need to instanciate an object to call an instance method:
public static void main(String[] args){
MyClass object = new MyCLass();
object.doThis();
}
public void doThis(){
System.out.println("Did this");
}
Android code is Java code, and has exactly the same rule.
Read the Java tutorial about instance and static members.
The issue is you need to rewrite it like so:
public class MyClass{ //fixed camel casing, classes start with upper case
public static void main (String[] args){ //fixed lettering
MyClass mc = new MyClass();
mc.doThis();
}
public void doThis(){
System.out.println("Did this");
}
}
This is nothing special about the difference between Android and Java, both will fail. The problem is you are trying to reference a non-static method from a static context, this could cause issues, as static indicates that the class does not need to be instantiated to invoke a function.
Static methods can be called without having an instance of the owning class, so therefore you can do:
myClass.doThis();
Since your doThis() method isn't static, you'd have to create an instance object like so:
myClass instance = new myClass();
instance.doThis();
The main() method that is calling your doThis() method is a static method, and an instance of myClass isn't required for it to be called. This means that any methods being called by your main method must be static, or called on an instance object (see 2nd example above).
An enclosing instance that contains is required
Below is the code. positionObj is the object that I am trying to use and it is giving me the above error.
It's unclear why.
package toolBox;
import toolBox.Secretary.positionObj;
public class PositionManagement {
public static HashMap<String, Secretary.positionObj> main(String vArg){
positionObj newPosition=new positionObj();
}
}
You're trying to use the non-static inner positionObj class without an instance of Secretary for it to belong to.
A non-static inner class must belong to an instance of its parent class
You should probably change positionObj to a normal class or a static inner class.
Alternatively, you can write someSecretary.new positionObj() to create an instance of the inner class that belongs to the someSecretary instance.
First create an object of Outer class. In this case I think "Secretary". Then create positionObj. Like this,
Secretary x = new Secretary();
Secretary.positionObj y = x.new positionObj();
The correct generic signature would be
public static HashMap<String, positionObj> main(String vArg)
you dont need to qualify positionObj since you already import it.
However, I am pretty sure a main method must conform to the signature below. If you intend to have main be the main method for your program, change the signature to
public static void main(String[] args) {...}
you can create a separate static method that returns a Map and invoke it from main.
As a note, all classes should begin with a capital letter, positionObj, should be PositionObj.