what is the difference in the behavior of this code? - java

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.

Related

Can we create an object of the class in which main function is defined in Java?

Is it possible to create object of class in which main method resides.I have been searching for this answer but I have been told that it depends on compiler some compiler will allow while others will not.Is that true?
Yes? The main method is just an entry point. The class is like any other, except it has an additional public static method. The main method is static and therefore not part of the instance of the object, but you shouldn't be using the main method anyway except for starting the program.
public class Scratchpad {
public static void main(String[] args) {
Scratchpad scratchpad = new Scratchpad();
scratchpad.someMethod();
}
public Scratchpad() {
}
private void someMethod() {
System.out.println("Non-static method prints");
}
}
Yes, you can create object for the class which has main method. There is no difference in this class and a class which don't have main method with respect to creating objects and using.

Understanding scope of objects in Java. Is there a better way?

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();
}

regarding static method in java

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.

Is it OK to call abstract method from constructor in Java? [duplicate]

This question already has answers here:
What's wrong with overridable method calls in constructors?
(8 answers)
Closed 5 years ago.
Let's suppose I have an abstract Base class that implements Runnable interface.
public abstract class Base implements Runnable {
protected int param;
public Base(final int param) {
System.out.println("Base constructor");
this.param = param;
// I'm using this param here
new Thread(this).start();
System.out.println("Derivative thread created with param " + param);
}
#Override
abstract public void run();
}
And here is one of a few derivative classes.
public class Derivative extends Base {
public Derivative(final int param) {
super(param);
}
#Override
public void run() {
System.out.println("Derivative is running with param " + param);
}
public static void main(String[] args) {
Derivative thread = new Derivative(1);
}
}
The point is that I want my Base class do some general stuff instead of copying it every time.
Actually, it's running fine, the output is always the same:
Base constructor
Derivative thread created with param 1
Derivative is running with param 1
But is it safe IN JAVA to start a thread calling the abstract method in constructor? Because, in C++ and C# it is unsafe in most cases, so far as I know.
Thank you!
This code demonstrates why you should never call an abstract method, or any other overridable method, from a constructor:
abstract class Super {
Super() {
doSubStuff();
}
abstract void doSubStuff();
}
class Sub extends Super {
String s = "Hello world";
void doSubStuff() {
System.out.println(s);
}
}
public static void main(String[] args) {
new Sub();
}
When run, this prints null. This means the only "safe" methods to have in a constructor are private and/or final ones.
On the other hand, your code doesn't actually call an abstract method from a constructor. Instead, you pass an uninitialized object to another thread for processing, which is worse, since the thread you're starting may be given priority and execute before your Base finishes its initialization.
Not a good idea since when run() is invoked, the Derivative object may not have been initialized. If run() depends on any state in Derivative, it can fail.
In your simple case it works. But then there's no point for the subclass. You can simply
public Base(final int param, Runnable action) {
new Thread(action).start();
It's a very bad practice to call an abstract method from a constructor. Methods called from constructors should always be private or final, to prevent overriding.
See this link to a question here
Passing this out of the constructor is called "letting this escape from the constructor", and can lead to some particularly nasty and weird bugs, because the object may be in an inconsistent state.
This is especially the case when this is passed to another thread, as in this example. Due to the JVMs right to reorder statements within a thread, you can get undefined behaviour/state occurring.

Multiple main() methods in java

I was wondering what the effect of creating extra main methods would do to your code.
For example,
public class TestClass {
public static void main (String[] args){
TestClass foo = new TestClass();
}
}
After the program initially starts up, foo will be created and it would have another public main method inside it. Will that cause any errors?
It will cause no errors. Just because you initialize an object, doesn't mean the main method gets executed. Java will only initially call the main method of the class passed to it, like
>java TestClass
However, doing something like:
public class TestClass
{
public static void main (String[] args)
{
TestClass foo = new TestClass();
foo.main(args);
}
}
Or
public class TestClass
{
public TestClass()
{
//This gets executed when you create an instance of TestClass
main(null);
}
public static void main (String[] args)
{
TestClass foo = new TestClass();
}
}
That would cause a StackOverflowError, because you are explicitly calling TestClass's main method, which will then call the main method again, and again, and again, and....
When in doubt, just test it out :-)
The main method is static, which means it belongs to the class rather than the object. So the object won't have another main method inside it at all.
You could call the main method on instances of the object, but if you do that it's literally just another way of calling TestClass.main() (and it's frowned upon by many, including me, to call a static method on an instance of an object anyway.)
If you're referring to multiple main methods in the same program, then this isn't a problem either. The main class is simply specified and its main method is executed to start the program (in the case of a jar file this is the main-class attribute in the manifest file.)
It won't have an additional main-method, as main is static. So it's once per class.
If you have multiple main-methods in your project, you will specify which one to launch when starting your application.
This is perfectly fine. Having multiple main methods doesn't cause any problems. When you first start a Java program, execution begins in some function called main in a class specified by the user or by the .jar file. Once the program has started running, all the other functions called main are essentially ignored or treated like other functions.
After searching for a Java Class with multiple main() methods or in plain words, overloaded main() methods, I came up with an example of my own. Please have a look
public class MultipleMain{
public static void main(String args[]){
main(1);
main('c');
main("MyString");
}
public static void main(int i){
System.out.println("Inside Overloaded main()");
}
public static void main(char i){
System.out.println("Inside Overloaded main()");
}
public static void main(String str){
System.out.println("Inside Overloaded main()");
}
}
I tested this Java Code on JDK 1.7 and works like a charm !
You need "public static void main(String args[])" to start with and then you can call overloaded main methods inside this main and it should work for sure.
Any comments and suggestion are highly appreciated. I am just a novice Java Developer willing to develop my Java skills.
Thanks,
PK
No, you can have any number of main-methods in a project. Since you specify which one you want to use when you launch the program it doesn't cause any conflicts.
You can have only one main method in one class, But you can call one main method to the another explicitly
class Expmain
{
public static void main(String[] ar)
{
System.out.println("main 1");
}
}
class Expmain1
{
public static void main(String[] ar)
{
System.out.println("main 2");
Expmain.main(ar);
}
}
when you run your Java class it will always look for the signature public static void main(String args[]) in the class. So suppose if you invoking by command line argument, it will look for the method Signature in the class and will not invoke other until if u explicitly inoke it by its class name.
class MainMethod1{
public static void main(String[] ags){
System.out.println("Hi main 1");
testig2 y = new testig2();
//in this case MainMethod1 is invoked/.......
// String[] a = new String[10];
// testig2.main(a);
}
}
class MainMethod2{
public static void main(String[] ags){
System.out.println("Hi main 2");
}
}
But when you try the same from eclipse it will ask for which class to compile. Means MainMethod1 or Mainmethod2. So if te class has the exact signature they can be used as individual entry point to start the application.
Coming to your question, If you remove the signature as u did above by changing the argument if main method. It will act as a normal method.
It is all about the execution engine of JVM. Remember, you write >java com.abc.MainClass on cmd prompt.
It explains everything. If main method is not found here it throws a run time Error:Main Method Not Found in class MainClass.
Now if main method is found here, it acts as the first point when Program Counters have to map and start executing the instructions. Referred classes are loaded then, referred methods may be called using the instances created inside. So, main is class specific though one class can have only one main method.
Please note, main method's signature never changes. You can have two overloaded main methods in same class, like
public static void main(String[] args) {}
public static void main() {} //overloaded in same class.
During Static binding, the original main is resolved and identified by execution engine.
Another interesting point to consider is a case where you have two different classes in of java file.
For example, you have Java file with two classes:
public class FirstClassMultiply {
public static void main (String args[]){
System.out.println("Using FirstClassMultiply");
FirstClassMultiply mult = new FirstClassMultiply();
System.out.println("Multiple is :" + mult.multiply(2, 4));
}
public static void main (int i){
System.out.println("Using FirstClassMultiply with integer argument");
FirstClassMultiply mult = new FirstClassMultiply();
System.out.println("Multiply is :" + mult.multiply(2, 5));
}
int multiply(int a, int b) {
return (a * b);
}
}
class SecondClass {
public static void main(String args[]) {
System.out.println("Using SecondClass");
FirstClassMultiply mult = new FirstClassMultiply();
System.out.println("Multiply is :" + mult.multiply(2, 3));
FirstClassMultiply.main(null);
FirstClassMultiply.main(1);
}
}
Compiling it with javac FirstClassMultiply.java will generate two .class files, first one is FirstClassMultiply.class and second one is SecondClass.class
And in order to run it you will need to do it for the generated .class files: java FirstClassMultiply and java SecondClass, not the original filename file.
Please note a couple of additional points:
You will be able to run SecondClass.class although it's class wasn't public in the original file!
FirstClassMultiply overloading of the main method
of is totally fine, but, the only entry point to your prog
will be the main method with String args[] argument.

Categories