Please ignore my arrogance......learning java these days, i came across this perfectly same question for my problem : Why can't I instantiate and create Object without main method? (Stack Overflow Error)
Expecting a possible downvote too...but please go through my question once!!!!
Code that i was trying :
public class Arrayprg{
Arrayprg ag = new Arrayprg(); //ignore this for a while and go thru code please
public static void main(String []args){
System.out.println("Hello Array");
new Arrayprg().declarearray();
}
public void declarearray()
{
int[] arr;
arr = new int[11];
new Arrayprg().assignarr(arr);
}
public void assignarr(int arr[])
{
int i;
for(i = 0; i < 11; i++)
{
arr[i] = i;
}
new Arrayprg().printarr(arr);
}
public void printarr(int arr[])
{
int i;
for(i = 0; i < 11; i++)
{
System.out.println(arr[i]);
}
}
}
Thinking logically, going through the code you'll see lots of new arrayprg()....what i thought of was to instantiate outside of methods and calling all methods through it there after, but i guess it is not allowed in java.
Whats causing my Problem
Going by the solution in quoted question, as it explain that below thing happens :
Create new instance of Arrayprg
-> ag = Create new instance of Arrayprg
-> ag = Create new instance of Arrayprg
-> ag = Create new instance of Arrayprg
Explanation given in that question
.....it is initialized whenever an instance of the class is instantiated. This will never terminate until you run out of memory and get the stack overflow. Run it with a debugger for a clearer view.
My Question
so i have Arrayprg ag = new Arrayprg(); in my program which is creating a loop every-time i create an instance but why is this called when i am calling the functions through new Arrayprg().
What i mean is that when i am calling the function through new Arrayprg() inside the methods why is Arrayprg ag = new Arrayprg(); getting called and creating the loop of error for Stackoverflow?????
This will cause a StackOverflowError.
The line you tell us to ignore, interestingly, is the culprit. When you instantiate a new Arrayprg then any object initializers are called, including new Arrayprg() which will then recursively try to keep invoking constructors without end. Remove that line, or put it in a static initializer. Better yet, just don't create that Arrayprg outside the main method as your Arrayprg does not need an instance of Arrayprg itself,
I would be more clear but I don't know what you're trying to achieve.
Solution : Change this line:
Arrayprg = new Arrayprg(); //ignore this for a while and go thru code please
to:
static Arrayprg a = new Arrayprg();
And you will no longer get your infinite recursion problem as now it will only create one instance of it shared between all instances - rather than each instance immediately creating a new one.
The Explanation
As part of constructing an Object in Java all member variable initializers, initializer code blocks, etc are all called as well as the constructor itself.
So in order to create a new Arrayprg one of the things it does is look for member variables that need initializing and initialize them.
In this case it finds Arrayprg a = new Arrayprg();, so in order to initalise the field a, it tries to create a new Arrayprg().
But that new Arrayprg() goes through the exact same process again, and again, and again, etc.
There are a number of ways to fix this - including:
Pass in the Arrayprg as a parameter to the constructor - so a new one doesn't need to be created.
Make the Arrayprg static - so only a single one needs to be created once rather than creating a new one each time
Lazy initaliziation on the Arrayprg so that you only create it the first time you try and access it rather than when the parent Arrayprg is created.
Why it doesn't happen in a method call:
The important thing that causes the recursion here is that the call happen during the creation of a new object. If trying to create a new object involves creating another copy of the same object then you will end up with infinite recursion which will then cause the failure.
So you can create a new object anywhere you like - so long as it is not inside the creation of itself.
class A {
A a = new A(); // Recursion
}
class A {
A() {
A a = new A(); // Recursion
}
}
class A {
A getNewA() {
return new A();
// This is fine as it doesn't happen during creation of an A
}
}
class A {
A() {
getNewA();
// Recursion as calling getNewA creates a new A, which calls getNewA, which....
}
A getNewA() {
return new A();
// This is fine on its own but is broken if called from the constructor
}
}
class B {
A a = new A();
// This is fine as B is not A, so you can create a new A within B.
}
Let's step through this visually.
Arrayprg = new Arrayprg();
So what do you need to create an object of type Arrayprg? Well you need to create it's fields.
Arrayprg = new Arrayprg();
And once again, you're telling the JVM to give you another Arrayprg object. By definition, this means making another Arrayprg object.
This is giving you a StackOverflowException.
Solution?
You shouldn't really be nesting types like this. It's pointless. You're inside the class already, so use it's methods.
public void declarearray()
{
int[] arr;
arr = new int[11];
assignarr(arr);
}
Follow this pattern, and you'll eliminate the need for the Arrayprg field.
Every time you create an instance of Arrayprg, you call this line: Arrayprg = new Arrayprg();, this means every time you create one, it creates another and another and another etc. You can instantiate objects there, but instantiating another object of the same type causes your infinite loop.
Also, in your methods (declareArr, assignArr etc) you can remove the 'new Arrayprg().' and just call the functions on the existing object.
In a class you can create objects outside any method, object cannot be of the same class.
It is meaningless. Take it as a rule.
Related
I'm working on a programm where a two lists are created and they have to be compared to find if there are two RECURS that are the same. I'm testing if it works (and have to use these methods) but I keep having the same problem; cannot find symbol.
public class Duplicate {
public Duplicate(){};
static ArrayList<Recurs> findDuplicate(ArrayList<Recurs> l1, ArrayList<Recurs> l2){
ArrayList<Recurs> l3 = new ArrayList<>();
for(int i=0; i<l1.size(); i++){
for(int j=0; j<l2.size();j++){
if(l2.get(i).equals(l1.get(j))){
l3.add(l1.get(i));
}
}
}
return l3;
}
}
This code is supposed to work. By the way, I've programmed a class called Recurs, which supposedly also works (I made another test and that worked ok where I created an equals method).
The problem comes now.
public class Test {
public static void main (String[] args){
Recurs o = new Recurs(3, "a");
Recurs e = new Recurs(2, "b");
Recurs m = new Recurs(4, "a");
Recurs n = new Recurs(2, "b");
ArrayList<Recurs> l1= new ArrayList<>();
l1.add(o);
l1.add(e);
ArrayList<Recurs> l2= new ArrayList<>();
l2.add(m);
l2.add(n);
ArrayList<Recurs> l3 = new ArrayList<>(findDuplicate(l1, l2))
}
}
I create a test where it is supposed to show me that this part is working, but i've got a problem at the last line of code, because it tells me it cannot find findDuplicate.
I'm new at using Java, if someone finds the problem, could they also point out the reason why it is happening?
Static methods "belong" to the class they are written in.
Here:
findDuplicate(l1, l2)
tries to call a (static) method in the Test class! Because it is an unqualified call, so the compiler will look inside the class that call takes place (which is Test). But there is no findDuplicate() method in the Test class!
Instead, it comes from the Duplicate class, so you need:
Duplicate.findDuplicate(l1, l2)
( alternatively, you could do a static import of that method, but for newbie learning things, I recommend to avoid doing that )
And of course, the method must also be visible to your Test class. So either the two classes should be in the same package, or as mentioned in various comments, that method needs the public modifier.
Without any modifier, your method will be only accessible to its own class, subclasses and the package. To make it accessible to your test, you could make it public but it is customary for test classes to share the same package as the classes they test by adding
package reverse.domain.name.app;
above both your class and your test class.
Secondly, your method is static, which means it is associated to the class, not its instance. this means that you should refer to it by its classname:
Duplicate.findDuplicate()
I have a great doubt as to what this action is called and how it is administered in memory.
Inside the main() method I make these sentences or instructions.
public static void main(String[] args) {
int i = 0;
int j = new Random().nextInt(100); // As it is called this way of acting or as it is called.
}
I have clear that what it does is directly invoke the Random class constructor method, invoke the nextInt method and generate a random number that is stored inside the int j variable but I don't know how to define this type of action and I don't know if it is correct to do this kind of instructions.
I'm curious to know what this type of action is called.
Thank you for your attention.
P.D : Sorry .. I'm learning
int j = new Random().nextInt(100);
is almost the same as
Random r = new Random();
int j = r.nextInt(100);
i.e. both create an instance (object) of the Random class, and then call a method of that instance.
The difference is that in the first case, you don't keep a reference to the created instance, so you can't access that instance again, and since no reference to that instance exists, it can be immediately garbage collected.
As Andy suggested, you can look at it as if you created an instance of the Random class and assigned it to a variable, called the nextInt() method, and then exited the scope in which that variable was declared:
int j;
{
Random r = new Random();
j = r.nextInt(100);
}
// at this point you have no access to the Random instance
One important note: this code is a bit shorter, and it's OK if you will not need to call nextInt() again. If you will, you better store the instance on Random class in a variable because the process of creating multiple Random objects for multiple int values is TOO heavy.
Well technically there is an instance of the class, since you see the keyword new.
What you see here is called method chaining.
You first call the constructor with new Random() and then chain the nextInt() method to it.
if you are curious how can you call a method without an instance of a class, the simple answer is you need a static class :) a good reference on static classes
But a simple example would be the Math class in java, with it you can do this:
double floor = Math.floor(7.343);
notice how you dont use "new" when invoking Math
How to call the Constructor multiple times using the same object
class a
{
a(int i)
{
System.out.println(i);
}
public static void main(String args[])
{
a b = new a();
int x = 10;
while( x > 0)
{
//Needed to pass the x value to constructor muliple times
}
}
}
I needed to pass the parameter to that constructor.
Constructor of a class A constructs the objects of class A.
Construction of an object happens only once, and after that you can modify the state of the object using methods (functions).
Also notice if programmer does not write any constructor in his class then the Java compiler puts the constructor for the class (public constructor without any parameters) on its own.
In the case where a constructor has been provided by the programmer, the compiler does not create a default constructor. It assumes, the programmer knows and wants creation of the objects of his/her class as per the signature of the explicit constructor.
Constructor calls are chained. Suppose there exists below class relationship.
Child.java extends Parent.java and Parent.java extends GrandParent.java.
Now if Child child = new Child(); is done, only one object is created and that is of Child.java, but the object also has all of the features of GrandParent first then with the features of the Parent and then the Child.
Hence first constructor of GrandParent.java is called then Parent.java is called and lastly the constructor of Child.java is called.
Constructors are special and different from other methods.
The intent of constructors is to create the object, so each time you use the new operator, the constructor is called and a new object is created. You can not call the constructor directly. You need the new operator to call it. Even if you see some class defining methods like getInstance(), it still uses the new operator to construct the object and return the created object.
*PS there are ways to create an object without calling constructor (like Serialization) but that is out of context of the discussion here.
Constructors are called only once at the time of the creation of the object.
Can you please be specific about what you want to achieve?
But I think you could try one of the following two things.
Calling the constructor to create a new object and assigning it to the object 'b':
b = new a(1);
Using the setter method:
void setI(int i){
this.i = i;
}
b.setI(1);
int x = 10;
while( x > 0)
{
a b = new a(x);
}
I am trying to pass values from my private static void main(...) into a class that has an array stack initialized in the constructor. I was wondering how to take the values I assign to a variable in the main() and push that value onto the array stack within this innerClass?
I know that the array stack works, I have implemented this class before without a problem, but I was only using the arrayStack() I had created and a main(). The addition of the third class is confusing me.
Without getting too deep in my code, I was hopping someone could explain (or point me to some resources) to me how to pass arguments to a stack that is initialized in a constructor, with arguments from the main() method of a different class (same package)?
Example of where I'm trying to get values to:
package program2;
public class Exec {
public Exec(DStack ds) {
/*I have initilized an arrayStack to hold doubles (i.e. DStack).
* I can use ds.push()/pop()/top() etc.
* I cannot take the value from Calculator.java and push that value
* here, which is what I need help understanding?
* */
ds.push(Calculator.i); //I would expect an error here, or the value stored in
//Calculator.i to be added to the stack. Instead program
//terminates.
}
}
Where I would like to take the values from:
package program2;
public class Calculator {
public static double i;
public static void main(String[] args) {
i=9; //I'm expecting that by using Calculator.i in the Exec class that
//I should be able to push 'i' onto the stack.
}
}
This question goes along with a question and answer I was able to get working yesterday here: Get answer from user input and pass to another class. There are three differences, one, I am no longer selecting an answer from the menu and performing an action. Two, I would like know how to get items on a stack versus comparing the String in a series of if/else statements. Lastly, I would like to know a little more detail about the nuts and bolts of this action.
You seem to completely misunderstand how an application works. When you launch your program, java executes your main method. All its instructions are executed in sequence until the end of the method is reached. If you haven't started any other thread from this method, when the last instruction in the main method has been executed, the program terminates.
In this case, the main method contains only one instruction:
i = 9;
So this instruction is executed, and since it's the last one, the program terminates. You don't even reference the Exec class anywhere, so this class isn't even loaded by the JVM.
If you want to use the Exec class, then you have to do something with is somewhere in the program. For example, you could do
i = 9;
DStack dstack = new DStack();
Exec exec = new Exec(dstack);
Note that storing something in a public static variable in order for some other object to be able to get this value is a very poor form of parameter passing. If an Exec object needs a value to work, then it should be an argument of its constructor:
public Exec(DStack ds, double value) {
ds.push(value);
}
and in the main method, you would use a local variable and not a public static variable:
double i = 9;
DStack dstack = new DStack();
Exec exec = new Exec(dstack, i);
If I understand your question correctly, you should create an instance of the Exec class. You can also create an instance of DStack within your program and pass it the Exec constructor after pushing the double value onto the stack.
package program2;
public class Calculator {
public static double i;
public static void main(String[] args) {
DStack dStack = new DStack();
dStrack.push(i);
Exec exec = new Exec(dStack);
}
}
I think you are confusing the concept of class vs. instance. You don't pass values to classes, you pass values to instances (static fields are sometimes called class variables and can make things confusing, but ignore that for now).
In a nutshell, a class is the code for that class you wrote. An instance is the actual thing that was spawned from that definition of class and actually does stuff. So the number one trick is to "instanciate" your class and create an instance. Then you pass whatever values you want to pass it like below:
class Foo {
public static main(String[] args) {
Bar bar = new Bar(); // <-- now you have an instance called bar
bar.arrayStack.push(args[0]); // <-- Now it's passed!
}
class Bar {
ArrayStack arrayStack;
Bar(){
arrayStack = new ArrayStack();
}
}
Good day,
I have a question on which in my code, one declaration is having an error outside a function.
The snippet is:
public class Gold {
Block[][] block = new Block[4][4];
this.block[1][4] = new Block(); //1
public void populate() {
this.block[1][4] = new Block();//2
}
}
The code this.block[1][4] = new Block(); number 2 is not having an error. However, the first code which is not inside the function is showing the error:
Illegal start type
Cannot find symbol
']' expected
invalid method declaration, return type required.
I just want to understand why this is hapenning and what I am missing.
Thanks
There is no element with index 4. The last element has index 3.
You can not initialize variables directly as you did above in case 1, You can initialize block[][] in constructor like :
public Gold(){
this.block[1][3] = new Block();
}
OR in block like :
Block[][] block = new Block[4][4];
{
this.block[1][3] = new Block();
}
You have a statement which must be in a block of code.
Try
public class Gold {
Block[][] block = new Block[4][4];
{ // initializer block
this.block[1][3] = new Block(); //1
}
You have two problems here, You need to initialize any object in a scope. Either you have to call the Number 1 line in a constructor or in a function or with in a block (enclosed with in{and}). Here you need to know difference between static block and non-static blocks.
Other problem you have is this.block[1][4] = new Block(); will throw an ArrayIndexOutofBounds exception as the length of the array is 4 and you are trying to insert and object at 5th place.
I think that you should place your code in constructor:
public Gold(){
this.block[1][4] = new Block();
}
In java class you can define variables or methods (including constructors) but can not use plain code in it.
this.block[1][4] = new Block(); //1
is an expression not a field initialization. It cannot be outside of a method body.
You need to wrap your code in a method, not in the class body. If its part of the initialization of the Gold class put it inside its constructor like:
public class Gold {
Block[][] block = new Block[4][4];
public Gold() {
this.block[1][4] = new Block();
}
}
The class body allows only variable declaration and instantiations, but not standard operations like changing an object's (your array) value.
EDIT: as other pointed out, the index 4 does not exist in an array of size 4, only indices from 0 to 3 can be accessed.
The code this.block[1][4] = new Block() is compiled but will fail on runtime: your array has 4 elements while index in java and all C-like languages starts from 0, so the max value of 4-elements long array is 3.
And you cannot write code outside methods in java, so if you try this you get compilation error.
This sentence
this.block[1][4] = new Block(); //1
cannot go outside a method or Initialisation block. If you want to initialize the array you have to do it on the declaration or inside a method (constructor could be a good place) or you have to use a Initialisation block.
Also check the array bounds. In Java arrays have 0 based indexes.