I think I am missing something. I want to call a method in an object from a statement in an object of a different class but if I do that the compiler tells me that it cannot find symbol.
public class Test1
{
public static void main (String[] args)
{
Second secondObj1 = new Second();
Third thirdObj1= new Third();
thirdObj1.accessMethodinSecondObj1();
}
}
class Second
{
int m1;
Second()
{
m1 = 0;
}
public void methodinSecond()
{
System.out.println(m1);
}
}
class Third
{
void accessMethodinSecondObj1()
{
secondObj1.methodinSecond();
}
}
So what I am trying to do is run method secondObj1.methodinSecond() from thirdObj1.accessMethodinSecondObj1(). Obviously, this example is a bit silly but it is related to a real problem - but I feel the full code would be too confusing.
I can solve the problem by passing the object reference for secondObj1 to thirdObj1 by changing the signature etc., but it seems very convoluted. Maybe there is a better way?
It seems to me that because I declared secondObj1 in the main method then the object itself is only visible within the main scope? Is there no way to allow objects of Second and Third to "talk" to each other directly, meaning call each other's methods?
secondObj1 is a local variable of the main method. A local variable is visible only in the block where it's declared. So it's visible only inside the main method. Not inside the method accessMethodinSecondObj1 of Third.
If you want this method to access the object referenced by `secondObj1, you need to pass that object as argument to the method:
In main:
thirdObj1.accessMethodinSecondObj1(secondObj1);
In Third:
void accessMethodinSecondObj1(Second s) {
s.methodinSecond();
}
Just like, to print the value of m1, you pass m1 as argument to the method println() of System.out.
The compiler message is about scope, yes.
But there is a more fundmental flaw in your code. What is you have another Second object and you want to call a method in that one? Your Third class objects expect any Second class object to be named 'secondObj1'.
You already indicated an solution, change te signature so that the object of class Second you want to access can be passed:
void accessMethodinSecondObj(Second secondObj)
{
secondObj.methodinSecond();
}
And then:
thirdObj1.accessMethodinSecondObj(secondObj1);
You're along the right lines. You are correct that the scope of secondObj1 is limited to the main method where it is created. So how do we pass secondObj1 to thirdObj1, as they're not globally available?
This first thing to note is that these objects have a relationship. Our class Third has a dependency upon Second. Third can't perform its responsibility in accessMethodinSecondObj1() without an instance of Second. In which case, we have a few options.
Thie simplest of which is to inject the dependency where it is needed. In this case, into the accessMethodinSecondObj1() method as such:
public class Third
{
public void accessMethodinSecondObj1(Second secondObj1)
{
secondObj1.methodinSecond();
}
}
To call this from main, simply:
public class Test1
{
public static void main (String[] args)
{
Second secondObj1 = new Second();
Third thirdObj1 = new Third();
thirdObj1.accessMethodinSecondObj1(secondObj1);
}
}
You could inherit from Second as to access its members and methods and call from within thirdObject1.accessMethodinSecondObj1() using super.methodinSecond(). But as we're dealing in abstractions here, it's a difficult solution to suggest as it may not make semantic sense in your domain.
In which case, another option is composition. We inject an instance of Second into Third via the constructor and that instance of Third then owns that instance of Second. By doing so, we ensure Third has an instance of Second (upon which it depends) when this method is called. This also enables the performing of validation operations on the passed instance of Second before we use it in accessMethodinSecondObj1().
public class Third
{
private Second secondObj1;
public Third(Second secondObj1)
{
this.secondObj1 = secondObj1;
}
public void accessMethodinSecondObj1()
{
this.secondObj1.methodinSecond();
}
}
In which case, within main we would do the following:
public class Test1
{
public static void main (String[] args)
{
Second secondObj1 = new Second();
Third thirdObj1 = new Third(secondObj1);
thirdObj1.accessMethodinSecondObj1();
}
}
As we can see
public void methodinSecond()
{
System.out.println(m1);
}
is not static and therefore in
secondObj1.methodinSecond();
you cannot call a method without creating an object if it is non-static
In your main method
Second secondObj = new Second();
the scope of the variable would be only inside the block so if you want to use it in the method of class Third pass it as a parameter to the method
thirdObj1.accessMethodinSecondObj1(secondObj);
and also change the method to
void accessMethodinSecondObj1(Second secondObj)
{
secondObj.methodinSecond();
}
Related
I have the following code:
public class Application extends ApplicationManager{
public static void main(String[] args) {
ProcessUtility.enableProcessUtility();
new Application().start();
}
}
and the class ApplicationManager code:
public class ApplicationManager {
public ApplicationManager() {
String configPath = "file:home" + File.separator + "log4j.xml";
System.setProperty("log4j.configuration", configPath);
logger = Logger.getLogger(ApplicationManager.class);
}
protected void start() {
logger.info("*** Starting ApplicationManager ***");
}
when I run the application class the start method of the parent will be called, can it be called without calling the parent default constructor?
my second question is the above code different from this code:
public class Application extends ApplicationManager{
public static void main(String[] args) {
new Application().start();
}
#Override
protected void start() {
ProcessUtility.enableProcessUtility();
super.start();
}
}
and the ApplicationManager class as above.
this is the code of the static method:
public static void enableProcessUtility() {
isCommon = false;
}
thanks in advance.
Calling a non static method (your start method) requires creating an instance of the class that contains the method (or a sub-class of that class). Creating an instance of a class requires invoking the constructors of the class and all its ancestor classes. Therefore you can't avoid executing the parent default constructor.
As for the second question, moving ProcessUtility.enableProcessUtility() to the sub-class's start method means that it will be executed each time you call the start method.
That said, in your example your main only creates one instance of Application and only calls start once for that instance. Therefore ProcessUtility.enableProcessUtility() will only be executed once in both snippets, and the behavior would be identical.
EDIT: Another difference between the two snippets is that the first snippet calls ProcessUtility.enableProcessUtility() before creating the Application instance, while the second snippet first creates the instance and then calls ProcessUtility.enableProcessUtility() from within start of the sub-class. If the behavior of the constructors (of either the sub class or the super class) is affected by the call to ProcessUtility.enableProcessUtility(), the two snippets may produce different outputs.
Your first question is answered here https://stackoverflow.com/a/10508202/2527075
As for your second question, the super constructor will be called before the ProcessUtility call in the second example, where in the first example the ProcessUtility call comes first.
We all know that we cannot call a non-static method from Java's static main method directly. I've written 2 ways to call non-static method from main (shown below).
What I wanted to ask is: Is there any significance difference between using code 1 and code 2 to overcome the limitation?
Code 1
public class Demo
{
public static void main(String[] args)
{
Demo demo = new Demo();
demo.printText();
}
public void printText()
{
System.out.println("Method successfully called.");
}
}
Code 2
public class Demo
{
public static void main(String[] args)
{
new Demo().printText();
}
public void printText()
{
System.out.println("Method successfully called.");
}
}
NOTE: In school, our professor told us "In Java, staticmethods of a class can be invoked through the name of the class in which they are defined, without having to instantiate an object of the class first."
But in code 2 no object was instantiated, yet I was able to call the non static-method?
There are 2 main things to be considered while using the first one over the second..
you will still have a reference to the Demo object, so you can call demo.someOtheMethod().
Your demo object will not be ready for Garbage collection as soon as printext() returns. i.e, it will not be ready until you actually exit main(). In the second case, it will be ready as soon as printext() returns..
The only difference is that you can reuse the value in the object demo later. However, you should not create an instance just to call such a method. The correct way to do this is to make the method static.
There is no any difference of executing code or the creating the object.
But in the second method, you don't have a reference to the object you created.(in first method, demo is the reference for the Demoobject) So you can't do any other thing with this object further, as there is no way of referencing it.
as example:
Suppose you had another method inside class Demo called foo1()
in first example you can run both method using a single object.
Demo demo = new Demo();
demo.printText();
demo.foo1();
but in the second method, You have to do it with 2 objects seperately.
new Demo().printText();
new Demo().foo1();
In Code1, you are creating an object using the class name as a reference variable, and calling that function and this would work very finely.
in code2, you are creating an anonymous object, which is basically used whenever we want to use the object only once in the lifecycle of the class.
In both code, the program will work finely.
When studying the java programming language, I meet the following statement
I am confusing about the statement marked with yellow. Especially, what does instance method mean here? If there is an example to explain this point, then it would be much appreciated.
If I have a method:
public static void print(String line) {
System.out.println(line);
}
... and then remove the static keyword ...
public void print(String line) {
System.out.println(line);
}
... it is now an instance method, can no longer be invoked from the class, and must instead be invoked from an instance (hence the name).
e.g.,
MyClass.print(line);
vs.
new MyClass().print(line);
That's really it.
You can call static methods without needing to intantiate an object:
TestObject.staticMethodCall();
For non-static methods you need to create an instance to call a method on:
new TestObject().nonStaticMethodCall();
Consider following sequence.
Define Class X with static void foo() a static method
Define Class Y which calls X.foo() in its main method
Compile the two classes and (somehow) run it
Change X.foo() to be a instance method by removing the static qualifier
Compile only X, not Y
Run the Y class again and observe the error.
On the other hand, if you had changed the body of X.foo in certain ways without changing its static-ness then there would have been no error. For more, look up "binary compatibility"
First of all, you should understand the difference between the class method and the instance method. An example is shown below.
public Class Example{
public static void main(String[] args) {
Example.method1();//or you can use method1() directly here
Example A = new Example();
A.method2();
}
public static void method1(){
}
public void method2(){
}
}
method1 is the class method which you can take it as the method of the class. You can invoke it without initiating a object by new method. So you can invoke it in such way: Example.method1()
method2 is the instance method which requires you to invoke it by initiating the instance of an object, i.e. Example A = new Example(); A.method2();
Additional:
The error is due to the removal of the static modifier of an class method like method1. Then method1 becomes an instance method like method2 which you have to initiate an instance to call.
When a class extends another, it inherits all methods and variables of the superclass. Both methods and variables can be used differently in the subclass, if you define it differently in the subclass with the same signature.
Now Oracle distincts between overwriting and hiding (http://docs.oracle.com/javase/tutorial/java/IandI/override.html).
It says that an instance method overwrites its superclass's method, while a class method hides it.
"The distinction between hiding and overriding has important implications. The version of the overridden method that gets invoked is the one in the subclass. The version of the hidden method that gets invoked depends on whether it is invoked from the superclass or the subclass."
Lets assume I have 2 classes Yes and Maybe. Yes extends Maybe.
Maybe has String a.
class Maybe {
String a;
public static void printOut() {
System.out.println("Maybe");
}
public void printAndSet() {
a = "Maybe";
System.out.println(a);
}
}
class Yes extends Maybe {
public static void printOut() {
System.out.println("Yes");
}
pubilc void printAndSet() {
a = "Yes";
}
}
class Print{
public static void mail(String[] args) {
Maybe m = new Maybe();
Yes y = new Yes();
Maybe.printOut();
Yes.printOut();
m.printAndSet();
y.printAndSet();
}
And I say: It will print out
maybe
yes
maybe
yes
But after I read the Oracle article I thought it would have to print out:
yes
yes
maybe
yes
Because the instance method overwrites its superclass method.
I'm quite sure I am right with the output, but I'm sure aswell, that Oracle knows
better so I'm thinking I just didn't understand the article.
It can't be true that when I call an instance method from an object of a superclass, that it uses the overwritten method.
So I do not understand why to distinguish overwriting and hiding!
Can someone help out?
Edit; Inserted code instead of describing the classes!
Static methods can't be overridden at all. They're not called polymorphically, since they don't act on an instance of the class, but on the class itself.
If you call Maybe.printOut(), it will call the static printOut() method defined in Maybe. The fact that there is also a method printOut() defined in Yes is irrelevant: those two methods have nothing in common, except their name.
Note that you could confirm or infirm your doubts by simply writing a program and executing it.
The problem with hiding methods only occurs when you start calling static methods on an instance of an object. This is very bad practice, and should never be done. If you don't respect this rule, and have the following:
Maybe m = new Maybe();
Maybe y = new Yes();
m.printOut(); // DON'T DO THAT: it should be Maybe.printOut();
y.printOut(); // DON'T DO THAT: it should be Maybe.printOut() or Yes.printOut();
the result will be maybe maybe, because in the case of static methods, what counts is not the concrete type of the objects (Maybe and Yes), but their declared type (Maybe and Maybe).
public class Parent {
public String test(){
return "p";
}
public static String testStatic(){
return "sp";
}
}
public class Child extends Parent {
public String test(){
return "c";
}
public static String testStatic(){
return "sc";
}
}
public class Demo{
public static void main(String[] args) {
Parent p =new Parent();
Child c = new Child();
Parent pc = new Child();
System.out.println(p.test());
System.out.println(c.test());
System.out.println(pc.test());
//Although this is not the correct way of calling static methods
System.out.println(p.testStatic());
System.out.println(c.testStatic());
System.out.println(pc.testStatic());
}
}
OUTPUT will be: - (static method vs instance method)
p
c
c
sp
sc
sp
Take the following example, based on your example:
public class SO11720216 {
static class Maybe {
public static void hidden() { System.out.println("static maybe"); }
public void overwritten() { System.out.println("instance maybe"); }
public void inherited() { hidden(); }
public void called() { overwritten(); inherited(); }
}
static class Yes extends Maybe {
public static void hidden() { System.out.println("static yes"); }
public void overwritten() { System.out.println("instance yes"); }
}
public static void main(String[] args) {
Maybe m = new Maybe();
Yes y = new Yes();
m.called(); /* prints:
instance maybe
static maybe
*/
y.called(); /* prints:
instance yes
static maybe
*/
Yes.hidden(); /* prints: static yes */
y.hidden(); /* bad style! prints: static yes */
}
}
The call to overwritten will be overwritten by each derived class. So every method will use the implementation belonging to the current object. On the other hand, the call to hidden will always use the implementation of the defining class. Hence Maybe.called will always call Maybe.hidden, and never Yes.hidden. To call Yes.hidden, you'll have to do so from within a method in Yes, or using a qualified name.
To phrase this differently:
To overwrite a method means that whenever the method is called on an object of the derived class, the new implementation will be called.
To hide a method means that an unqualified call to that name (like the hidden() call in the inherited() method of my above example) in the scope of this class (i.e. in the body of any of its methods, or when qualified with the name of this class) will now call a completely different function, requiring a qualification to access the static method of the same name from the parent class.
Perhaps your confusion comes from the fact that you assumed overwriting to affect all calls to the method, even for objects of the base class.
Suppose the classes has code like this:
class C {
public static void show() {
}
}
class CTest {
public static void main (String[] args) {
C.show();
}
}
Then will it be perfectly legal to conclude that while referring to class C to access the static method show() here, behind the scene Java is actually calling the show() method through Java reflection ?
I.e. is it actually doing something like this
Class test = Class.forName(C);
test.show();
to call static methods?
If not, then how is it actually calling the static methods without creating objects?
If the above explanation is true, then how we'll justify the statement that "static members are only associated with classes, not objects" when we're actually invoking the method through a java.lang.Class object?
The JVM doesn't need to do anything like Class.forName() when calling a static method, because when the class that is calling the method is initialized (or when the method runs the first time, depending on where the static method call is), those other classes are looked up and a reference to the static method code is installed into the pool of data associated with that calling class. But at some point during that initialization, yes, the equivalent of Class.forName() is performed to find the other class.
This is a specious semantic argument. You could just as easily say that this reinforces the standard line that a static method is associated with the class rather than any instance of the class.
The JVM divides the memory it can use into different parts: one part where classes are stored, and one for the objects. (I think there might have been third part, but I am not quite sure about that right now).
Anyways, when an object is created, java looks up the corresponding class (like a blueprint) and creates a copy of it -> voila, we have an object. When a static method is called, the method of the class in the first part of the memory is executed, and not that of an object in the second part. (so there is no need to instantiate an object).
Besides, reflection needs a lot of resources, so using it to call static methods would considerably impact performance.
For extra info:
The called class will get loaded when it's first referenced by calling code.
i.e. The JVM only resolves and loads the class at the specific line of code that it first needs it.
You can verify this by using the JVM arg "-verbose:class" and stepping through with a debugger.
It will call ClassLoader.loadClass(String name) to load the class.
You can put a println statement into the ctor, to verify, whether it is called or not:
class C {
public static void show () {
System.out.println ("static: C.show ();");
}
public C () {
System.out.println ("C.ctor ();");
}
public void view () {
System.out.println ("c.view ();");
}
}
public class CTest
{
public static void main (String args[])
{
System.out.println ("static: ");
C.show ();
System.out.println ("object: ");
C c = new C ();
c.view ();
c.show (); // bad style, should be avoided
}
}