How does this work?
EDIT: Being static is not a good explanation, because I can use non-static methods and it will all work. Updated the code to reflect that.
I have this in a file called Foo.java:
// This is in the Foo.java file
class Test {
public void printSomething() {
System.out.println("In Foo.Test");
}
};
and this in a file called Caller.java:
// This goes in the Caller.java file
public class Caller {
public static void main(String[] args) {
Test test = new Test();
test.printSomething();
}
}
I can execute my Caller and it will print In Foo.Test. How can this not be a compilation problem? I don't even have a Foo class created. I don't even have to define Foo.Test in the Caller.
This is on Eclipse Luna, Java8.
Java is weird like that. You could have a file without any lines of code and it would still compile. Go on try it.
Now, I think you are confusing Test with Foo.Test (I understand, it's Friday).
Intrinsically what you defined is this:
public class Foo {} // this is by default, but don't try to use it because you didn't define the scope
class Test {}
And your perplexity is "OMG, Test is the impure offspring of a non-existing class!!!", because you were expecting something like
public class Foo {
class Test {}
}
This has nothing to do with a method being static. It is about quirkiness in the javac.
Happy Friday everyone! Time for happy hour.
The main-Method of the Foo.java is declared static
calling static methods works without creating a object of the class.
E.g you can create following Method in Foo.java
class Test {
public static void test(String test) {
System.out.println(test);
}
};
Now you can call Test.test("No object will be created"); and there will be NO instance of Test
A java file could contain single public class, but it could have as much non-public classes (package-local in your case) as you wanted.
Foo.Test is for inner classes. The one you declared is top level type.
Related
I am a C++ programmer trying to understand best practices of the Java language. Please tailor your responses accordingly :)
I worked out an example and I don't understand why/how the behavior I observed is possible.
//HelloWorld.java
public class HelloWorld{
public static void main(String []args){
Newfile nf = new Newfile();
nf.setTest(5);
System.out.println(Integer.toString(nf.test.i));
System.out.println("Hello World");
}
}
//Newfile.java
class TEST {
public int i;
}
public class Newfile{
public TEST test = new TEST();
public int setTest(int i) {
return test.i = i;
}
}
// THIS WORKED
/*
5
Hello World
*/
Since Test is private (well I presume) then how can HelloWorld even manipulate the contents of TEST (i.e. the i member)?
Now the strange part, when I moved TEST to a private inner class of Newfile it now behave as I would've expected the above experiment to behave and I got:
i in Newfile.TEST is defined in an inaccessible class or interface
Since TEST is private (well I presume)
Nope. It's actually package-private.
From Java Tutorials:
If a class has no modifier (the default, also known as package-private), it is visible only within its own package
EDIT
Both your HelloWorld and your TEST classes are members of the same package (in your case, since you don't appear to have specified the package explicitly, they are members of the unnamed package). Therefore, even though TEST is package-private, it is accessible from HelloWorld.
Now the strange part, when I moved TEST to a private inner class of
Newfile it now behave as I would've expected the above experiment to
behave and I got:
i in Newfile.TEST is defined in an inaccessible class or interface
By makingTEST a private inner class of Newfile you make it accessible only to members of Newfile class itself, so, naturally, it's no longer accessible from HelloWorld in this case.
I'm still a bit knew to Java. Only done PHP and a bit of javascript most my life. I had a question concerning the order you have your classes/methods encapsulated inside each other. Does it matter? Is there a better professional way with doing this? Sorry for the newbie question.
Method 1 (class after main())
public class myClass {
public void main(String[] args) {
//Body Code Here
}
}
class myClass {
//Body Code Here
}
Method 2 (class inside main())
class mainClass {
public void main(String[] args) {
//Body Code Here
class myClass {
//Body Code Here
}
}
}
Method 3 ( class before main())
class myClass {
//Body Code Here
}
class mainClass {
public static main(String[] args) {
//Body Code Here
}
}
You need to have all your methods inside the body of your class. Outside it, you can only import some libraries for example java.util.Scanner(for reading from the console).
And you can insert methods before or after the Main method, both ways when you run the program they will be read.
Your main method, as any other method, must be within a class. Therefore only the first method would work.
Your first method will work.
as the main method should be in the class then only jvm will compile it.
I took the following code from the K&B book "SCJP Sun Certified Programmer for Java 6 Study Guide":
class A { // 1
void m() {
System.out.println("outer");
}
}
public class TestInners {
public static void main(String[] args) {
new TestInners().go();
}
void go() {
new A().m();
class A { // 2
void m() {
System.out.println("inner");
}
}
}
class A { // 3
void m() {
System.out.println("middle");
}
}
}
As stated in the book, this code prints "middle". I infer that the class declaration marked as "3" is shadowing the one marked as "1", which is external to TestInners class.
If the classes were in different packages, I could resolve the ambiguity by qualifying one of them with the package name. But in this case the classes are not only in the same package but in the same file. How can I get an instance of the external class?
I saw the same question here but the accepted answer implies to modify the code adding an enclosing class to the whole thing. My question is how to get the instance using any type of qualifier or reference, if it's even possible.
Assuming your class is in package com.test, all you need to do is use
new com.test.A().m();
using the fully qualified name of the class.
If your classes are in the default package, ie. no package declaration, then you are out of luck and can't access the outer A.
In C++, you can explicitly address global scope by prefixing your symbol with ::, however, Java does not have such a thing.
So if you really want to get the outer A, you have to bite the bullet and do some other sort of enclosure, by for example wrapping it in another class or package.
EDIT: Here is another reason why.
object of innner-A can't be created before defining it.so use new A().m(); after define innner-A inside go() to access inner class object.
void go() {
class A {
void m() {
System.out.println("inner");
}
}
new A().m();
}
to access outer-A you have to append package name,in default package it is impossible to access outer-A.
I have built a small (and 3 methods only!) api for myself, and I want to be able to call it like how you would call a method in Powerbot (A Runescape botting tool (I use it, but for programming purposes, not for actual cheating purposes)), without creating an Object of the file you'd require. How would i be able to do this?
You will need to create static methods, so you will need to do something like so:
public class A
{
public static void foo()
{
...
}
}
And then, you can call them like so:
public class B
{
...
A.foo();
}
Note however that static methods need to be self contained.
EDIT: As recommended in one of the answers below, you can make it work like so:
package samples.examples
public class Test
{
public static void A()
{
...
}
}
And then do this:
import static sample.examples.Test.A;
public class Test2
{
...
A();
}
If you use the static keyword when importing your class, you can use its methods as if they belong to the class you're importing them to. See:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/static-import.html
And of course your "api methods" need to be static as well.
The best way i found out for me was to extend my activity (If i said it right)...
MAIN CLASS
public class myMainActivity extends myMiniApi{
...
}
I think this is a better way (my opinion) to do this, Just call your method like you normally would as if it were in the same class. example:
randomMethod();
Once a class is loaded is there a way to invoke static initializers again?
public class Foo {
static {
System.out.println("bar");
}
}
Edit:
I need to invoke the static initializer because I didn't write the original class and the logic I need to invoke is implemented in the static initializer.
Put the initalisation code in a separate public static method, so you can call it from the static initializer and from elsewhere?
One circumstance in which the logic would be run more than once is if the class is loaded multiple times by different ClassLoaders. Note that in this instance, they are essentially different classes.
Generally, though, these are one-shot deals. If you want to be able to invoke the logic multiple times, do as others have suggested and put it in a static method.
I agree with Earwicker's answer. Just extract the static initialization to a separate static method.
public class Foo {
static {
Foo.initialize();
}
public static void initialize() {
System.out.println("bar");
}
}
In case you really want the exact answer to your exact question, the answer is no. It's not possible to invoke a static initializer or an instanceInitializer via reflection.
The docs clearly says :
for getDeclaredMethod(String name) :
If the name is "<init>" or "<clinit>" a NoSuchMethodException is raised.
for getDeclaredMethods() :
The class initialization method is not included in the returned array.
So no, it's not possible to invoke it, even via reflection.
you could try extending the class which contains the static code, and then put in your own static initializer. Not quite sure if it works, but :
public class OldBadLibraryClass {
static {
System.out.println("oldBadLibrary static init");
}
}
//next file
public class MyBetterClass extends OldBadLibraryClass {
static {
System.out.println("MyBetterClass init");
}
}
public class Test {
public static void main(String[] args) {
new MyBetterClass();
}
}
see if the above prints in the order you expect. On my machine, it worked.
Though this is totally a hack, and is quite brittle. It would really be much better to modify the old class to have an init() method that can be overridden.
Here https://stackoverflow.com/a/19302726/2300018 is a post from me, where I re-load a utility class to re-run the static initializer for unit testing.