I've been flustered over trying to figure out how to call a method from an instance of a class from a different class. For example:
public class Test1
{
public static void makeSomeInst()
{
Test1 inst = new Test1();
inst.fireTest();
}
public void fireTest()
{
System.out.println("fireTest");
}
public Test1()
{
}
}
no problem with understanding the above, but what If I want to do something to inst from a class called Test2, how would I do that? The below example doesn't work:
public class Test2
{
public static void main(String[] args)
{
Test1.makeSomeInst();
inst.fireTest();
}
}
And just to be extra clear, I get that I can call static references without instantiating, but I just want to know, in this specific case
What is the syntax to reference the test1 object called inst from the Test2 class?
what If I want to do something to inst from a class called Test2, how would I do that?
First of all you have to teach the Test2 class what Test1 is.
public class Test2
{
public doSomething()
{
inst.fireTest();
}
public Test2(Test1 inst)
{
this.inst = inst;
}
private Test1 inst;
}
Then teach the inst2 object what inst is.
public class Test1
{
public static void main(String[] args)
{
Test1 inst = new Test1();
Test2 inst2 = new Test2(inst); // <- new code
inst2.doSomething(); // <- new code
}
public void fireTest()
{
System.out.println("fireTest");
}
public Test1()
{
}
}
You only need one main to start the show. Flow of control can still pass through other objects. But at this point I wouldn't call these independent tests. I only used that name to match your code.
What you're looking at is something called reference passing. The fancy term for it is Pure Dependency Injection*. The basic pattern is to build an object graph in main. Once that's built call one method on one object to start the whole thing ticking.
In main you build every object that will live as long as your program does. What you wont find built here are objects that are born later, such as timestamps. A good rule of thumb is to build each of these long lived objects before doing any real work. Since they know about each other they can pass flow of control back and forth between them. There's a lot of power there and if not used well it can get confusing. Look into Architectural Patterns to help keep that simple.
The principle followed here is to separate use from construction. Following that allows you to easily change your mind about what talks to what in one place. It's nice when a design change doesn't force you to rewrite everything.
You have to save your instance somewhere.
If Test1 should be a singleton, you can do:
public class Test1
{
private static Test1 instance;
public static Test1 getInstance()
{
return instance == null ? instance = new Test1() : instance;
}
public static void main(String[] args)
{
Test1 inst = getInstance();
inst.fireTest();
}
public void fireTest()
{
System.out.println("fireTest");
}
}
and in Test2:
public class Test2
{
public static void main(String[] args)
{
Test1.getInstance().fireTest();
}
}
//Edit
As I just learned from #Thomas S. comment, singletons are not a good solution.
See #candied_orange's answer for a better implementation.
Related
Is it able to avoid using "static" when call variable from another class? thank you very much
Here is my code.
class Hello {
public static String say = "Hello World"; //I using static
public void born() {
System.out.println(say);
}
}
public class SayHello extends Hello {
public static void main(String[] args) {
Hello myHello = new Hello();
myHello.born();
System.out.println(say);
}
The Output:
Hello World
Hello World
If I use public String say = "Hello World";
it output Hello World null
AnyIdea to avoid using "static" when call variable from another class?
thank you very much
If you remove the static, it will not compile. Static fields can be marked private, if you want to hide them. So then they are reachable by all instances of the class Hello only. The proper way of modifying or getting would be:
class Main extends Hello {
public static void main(String[] args) throws Exception {
Hello myHello = new Hello();
myHello.born();
// System.out.println(say); //doesn't allow access
// System.out.println(Hello.say); //doesn't allow access
System.out.println(myHello.getSay());
}
}
class Hello {
private static String say = "Hello World"; //private
public void born() {
System.out.println(say);
}
public String getSay() {
return say;
}
}
A static variable is common to all the instances (or objects) of the class because it is a class level variable. In other words you can say that only a single copy of static variable is created and shared among all the instances of the class.
So if you don't want to use static, then you can't use it in the other instances of class.
Yes, if you don't declare it static you can reference it from an instance: myHello.say.
It is the same as for calling a function.
public class SayHello extends Hello {
public static void main(String[] args) {
Hello myHello = new Hello();
myHello.born();
System.out.println(myHello.say);
}
}
For a constant, ie. a String that never changes and is the same for all instances of the class, it makes sense to declare it static and use it as such.
If you don't mark the string as static you will get a compilation error because when you do System.out.println(say) in the main method you are using say in a static context (since the main method must be static).
If you remove System.out.println(say); and just leave myHello.born(); then there's no need for say to be static because you'll only be using it from non-static methods (i.e. the born() method). You can see it in this example where I commented that line and defined say as not being static.
Another option would be to make the println like this, since the variable is public: System.out.println(myHello.say);
I have the following two classes:
public class Prod
{
public void logon(){
System.out.println("'\u000CProd logon");
addUser();
}
public void addUser(){
System.out.println("Prod addUser");
}
}
public class Dev extends Prod
{
public void addUser(){
System.out.println("Dev addUser");
}
public static void main(String[] args){
Dev test = new Dev();
test.logon();
}
}
Is there a way to make all the methods static and then test whether the Dev.addUser() is working correctly?
Here's what I would like to be able to do:
public class Prod
{
public static void logon(){
System.out.println("'\u000CProd logon");
addUser();
}
public static void addUser(){
System.out.println("Prod addUser");
}
}
public class Dev extends Prod
{
public static void addUser(){
System.out.println("Dev addUser");
}
public static void main(String[] args){
logon();
}
}
When I run the main() in Dev we should get:
Prod logon
Dev addUser
Is there a way to make all the methods static and then test whether the Dev.addUser() is working correctly?
No, there isn't.
This is really fundamental Java: you want to use static methods in a polymorphic context. But static methods are not polymorphic. There is no true inheritance, there is no overwriting of static methods. See here for lengthy explanations why that is. Repeat: the desired output can't be achieved in a purely static way, built around class A extending class B. End of story.
And as already said: this is also wrong from a conceptual point. Because of such restrictions, static should only be used carefully in Java. Simply go with the non-static code you have right now.
Unfortunately your question isn't really clear what exactly you intend to test, therefore I can't help with that part.
I took this example from a tutorial. Given below class was created to restrict multiple objects creation in same class.
package interview;
public class Test1 {
private static Test1 tstObj = null;
private Test1() {
}
public static Test1 createObject() {
if (tstObj == null) {
tstObj = new Test1();
}
return tstObj;
}
public void display() {
System.out.println("Singleton class Example");
}
}
But when I tried to create multiple objects from the same class in another class in same package I got succeeded.
package interview;
public class Test {
public static void main(String[] args) {
Test1 myobject = Test1.createObject();
myobject.display();
Test1 myobject1 = Test1.createObject();
myobject1.display();
Test1 myobject2 = Test1.createObject();
myobject2.display();
}
}
How come this happened or am I not understanding the consepnt of multiple object creation ???
Please help.
Your second and third calls to Test1#createObject() are not actually creating another instance of the singleton class, q.v. the code for the constructor:
public static Test1 createObject() {
// create a single instance the first time around
if (tstObj == null) {
tstObj = new Test1();
}
// otherwise return the instance which already exists
return tstObj;
}
Note carefully that the if statement only instantiates the singleton if the reference be null, which ideally should only happen the very first time your app calls createObject().
I've got three classes:
One class which handles my main game operations. Its name is 'PlatformerGame'.
Note: Removed all game-related stuff.
public class PlatformerGame {
public PlatformerGame()
{
}
}
Then, I've got a class called 'PlatformerSingleton' which is meant to provide exactly one instance of the PlatformerGame.
public class PlatformerSingleton {
private static PlatformerGame game;
protected PlatformerSingleton()
{}
public static PlatformerGame getGame()
{
if (game == null)
game = new PlatformerGame();
return game;
}
}
And lastly, I've got the entry point of my application which is supposed to do nothing but get the instance of PlatformerGame and call its 'start' method.
public class Entry {
public static void main(String[] args) {
new PlatformerSingleton.getGame().start();
}
}
However, this is where the error happens:
What does this error mean and how can I prevent it? Also, are there any better approaches to implement this?
Note: I require access to the singleton instance from multiple classes, therefore I need this singleton class.
Don't add new in the line new PlatformerSingleton.getGame().start();
just change your line to:
PlatformerSingleton.getGame().start();
you are not creating new object here, you are just calling the static method of PlatformerSingleton class in which the object of the class is created using Singleton Design Pattern
Remove the new in that call:
new PlatformerSingleton.getGame().start();
Currently, it looks like you're trying to instantiate a class called PlatformerSingleton.getGame (a static nested class called getGame inside PlatformerSingleton).
You're looking for the static method inside PlatformerSingleton. Since it's static, you don't want to instantiate using new at all.
The compiler sees that the syntax is correct, but it doesn't find such class and thus throws an error. These kinds of errors are a bit tougher to correctly debug (as the actual error is syntactical), so you need to look a bit farther to fix it.
Just remove the newkeyword (you don't need new because you're creating PlatformerGameinstance inside of the getGame method):
public static void main(String[] args) {
PlatformerSingleton.getGame().start();
}
Since getGame() is a static method, you do not need to use the new keyword to call the method.
public static void main(String[] args) {
PlatformerSingleton.getGame().start(); // new keyword is not required
}
If getGame() was not static, only then it would have required an instance of PlatformerSingleton class for it to be called and that would have looked like
public static void main(String[] args) {
new PlatformerSingleton().getGame().start(); // if getGame() was a non-static method
}
I have two packages inside my project, a and b.
a is my "main class" that runs when the program runs but I need to make b run from a (if that makes sense).
I'm sure its something along the lines of PackageB.BMain but I'm not sure.
Edit:
Okay so I've learned a few new things, to start my main project is RevIRC, inside that I have two packages, MainChat and RevIRC, now when I run the program RevIRC is ran, I need to make Mainchat run when RevIRC is ran.
Like I said before I'm sure its something along the lines of RevIRC.MainChat.ChatMain() but I can't seem to figure it out.
You have 2 options:
Either create a new instance of B from A, like so: PackageB.BMain b = new PackageB.BMain();
Access the methods in BMain in a static way like so: PackageB.BMain.someMethod();`
Note that you can use either of these exclusively or mix them up together, however, it all depends on how you have written your BMain class.
So for instance:
package PackageB
public class BMain
{
public BMain()
{ }
public void foo()
{
System.out.println("This is not a static method. It requires a new instance of BMain to be created for it to be called");
}
public static void bar()
{
System.out.println("This is a static method. It can be accessed directly without the need of creating an instance of BMain");
}
}
Then in your main class (the class which has the main method):
package PackageA
public class AMain
{
public static void main(String[] args)
{
PackageB.BMain.bar();
PackageB.BMain bInstance = new PackageB.BMain();
bInstance.foo();
}
}
If you have two main methods it will either run from A or B. The JVM will choose the first main method it sees IIRC.
Have a standalone class that will have main. And create your classes there.. ?
import a.Class1;
import b.Class2;
public class MainController
{
public static void main(String args[])
{
Class1 class1 = new Class1() ;
Class2 class2 = new Class2() ;
//Both class no start at the "same" time.
}
}
if i am not wrong you want to run main method of class B from class A.
That you can call using B.main(arg[]);
eg :
package a;
public class A
{
public static void main(String[] args)
{
System.out.println("This is main method of class A");
B.main(null);
/*pass any args if you want or simply set null arg*/
}
}
package b;
public class B
{
public static void main(String[] args)
{
System.out.println("This is main method of class B");
}
}
i hope this simple example will clear your doubt.
you can refer to link which contains Java tutorial for beginners.