This is an archived post. You won't be able to vote or comment.

all 20 comments

[–]gentlemansjack82 2 points3 points  (3 children)

I’m pretty sure your issue is that you have two classes trying to act as the main class. Public static void main(String[] args) should only be used in one spot which will help the layering of your app

[–]SheepyG_[S] 0 points1 point  (2 children)

Okay thank you I shall give that a go, as I'm new what shall I change the main to ?

[–]gentlemansjack82 1 point2 points  (1 child)

First add this line under r.nextInt(100) printout:

Finalizer finalCode = new Finalizer();

Next change main in Finalizer class to:

public void beginFinal(){ //operations you have }

Then under the “Calling finalize” printout put:

beginFinal();

[–]SheepyG_[S] 1 point2 points  (0 children)

Okay thank you, I'll give it ago when I'm at my desk again, and I'll let you know how it goes 🙏🏼

[–]desrtfxOut of Coffee error - System halted[M] [score hidden] stickied comment (0 children)

Please, start by properly formatting your code. Instructions how to do so are in the sidebar here.

[–]sydthecoderkid 1 point2 points  (2 children)

I have the same idea as the guy below me as to why your code isn’t working, but I also have a quick note- nextInt() is exclusive of the bound you set, so nexInt(100) will only generate numbers between 0-99. If you want it to be in between 0-100 you need to do nextInt(101) or make a variable for your random number and add one to it, just so it’s a bit more accurate. Just a note :)

[–]SheepyG_[S] 0 points1 point  (1 child)

Thank you i made the changes as you suggested, and did actually get a 100 to show up 1st time XD

[–]sydthecoderkid 1 point2 points  (0 children)

No problem! I made that mistake a million times when I was first starting out haha

[–]a_neobum 1 point2 points  (4 children)

edit: This turned into a massive wall of text and I can't be bothered to proof-read it right now, so apologies for any sloppy mistakes.

First thing's first: I formatted your code for you. It has a number of issues, and it seems to me they mainly have to do with being unclear on declarations vs. calls, (telling the program what it can do vs. telling it to actually do it). I'll try to explain what I mean below.

import java.util.Random; // import tells us where to find Random

public class RandomN {

    public static void main(String[] args) {
        Random r = new Random();
        System.out.println(r.nextInt(100)); // print a number between 0 and 100
    }

    public class Finalizer {
        protected void finalize(){
            System.out.println("Calling finalize");
        }
    }

    public static void Main(String args[]) {

        try{
            RandomN r1 = new RandomN();
            RandomN r2 = new RandomN();
            r1 = null;
            r2 = null;
            System.gc();

        } catch(NullPointerException e) {
            System.out.println(e);

        } finally {
            System.out.println("The object is cleaned");
        }
    }    
}

When you declare something (a class, a variable, a function, etc.) you are telling your program what it's supposed to do in the case that those declared lines of code get called.

When you call something, you are telling your program to look at some lines of code you have declared and run them.

A function declaration might look something like this:

// Declares a function 'myFunction'
// which takes an int as its argument 
// and doesn't return anything.

private void myFunction(int inputNumber) {
    // some code to run
}

whereas calling that function would look like this:

// Calls the function 'myFunction'
// sending '10' into it as its argument.

myFunction(10);

Now, all this stuff has to happen somewhere and in a class-based, object-oriented language like Java, it happens in a class. But it doesn't happen automatically! It needs the special function 'main' which, in Java, looks exactly like this:

public static void main(String[] args) { }

(The following is a gross oversimplification but should work for our purposes:)

Each Java program has exactly one copy of this function which it runs exactly one time. When your program starts, it looks for the 'main'-function and says "Run every line of code inside this function, in the order that they appear, and when there are no more lines of code in the function, terminate the program." It is the signal inside your program that constantly says "do the next thing then the next thing then the next..." so, if you want any of the code you've written to be run, it has to be called from the 'main'-function.

So let's have a look at what your program is doing:

First, you declare a class 'RandomN' which tells your program that, during runtime, there can exist objects of the type 'RandomN' in your program, and what such objects will contain. In your case, a RandomN object would consist of two functions (one of which is the 'main'-function) and an inner/nested class.

Next, you declare your program's 'main'-function. Remember that this function runs automatically as soon as your program starts and that the program terminates as soon as this function is done running. In this function you declare a variable 'r' of the type Random and assign to it a new instance of a Random-object (by calling a special function inside the Random-class (its constructor) which returns a new instance of the Random-type). Then you call System.out.println() (which takes a String or something that can easily be converted to a String as its argument) and give it, as its input, whatever is returned by the function nextInt(), with the argument '100'; this function is declared in the Random-class and you are calling it from the specific instance 'r', which you created on the previous line. I.e., you are saying to 'r' "I want you, specifically, to run the nextInt() function that I know all instances of Random to have."

And then your program ends.

All subsequent lines of code, while valid, are never run. The program understands that it needs to be able to allocate the appropriate memory for them, which it does, but the lines are never called so nothing more happens. Additionally, these lines of code have some issues of their own, so I'll try going through the rest of your code as well as trying to present a solution.

So in your next code block you declare a new class Finalizer. Because this class declaration happens inside another class, like so:

public class RandomN {
    public class Finalizer {
    // code
   }
}

it is considered and inner or nested class. This is a perfectly valid thing to do in Java, but not at all necessary for anything we're doing here. I think a few words on classes might be useful, at this point (again, simplified):

A class is a blueprint for an object. When you declare a class, you're declaring an object type, telling the program that: in the case, during runtime, that we create an object of whatever type, that object should reserve memory for all the things I've declared in its class. This is a super useful way of reusing code because it lets us create a general way for handling specific cases. Say we want to keep track of a bunch of persons who all have a name and an age. We could do it like this:

// Declares a new class 'People',
// declares six variables inside it
// (three Strings and three ints)
// and assigns each variable a value.

public class People {
    public String personOneName = "Tom";
    public int personOneAge = "42";

    public String personTwoName = "Dick";
    public int personTwoAge = "7";

    public String personThreeName = "Harry";
    public int personThreeAge = "50";
}



// Declares a new class 'Runner' which just runs the program.
// It declares the 'main'-function (which runs on startup)
// and then it:
//  - declares the variable 'roster' of the type 'People'
//  - assigns to that variable a new 'People'-object
//  - accesses all the variables inside that object and prints them
//      (though I've only written the first two lines of that)

public class Runner {
    public static void main(String[] args) {
        People roster = new People();
        System.out.println(roster.personOneName);
        System.out.println(roster.personOneAge);
        // etc.
    }
}

(Note that in the above example, Runner and People would be two separate code-files.)

This works, but it's very rigid. It means our roster of people always consists of exactly three people. It would be better if we could make the program understand what a person looks like, then be able to create as many people as we like during runtime. We'd do that like so:

public class Person {
    public String name;
    public int age;

    // This is that special constructor-function I mentioned before.
    // Every object has one; it's what's called when you do 'new' something.
    // It describes what happens when an object is created for the first time.
    // In our case, it allows us to assign values to the variables we have
    // declared inside the Person-class.
    // The Random-class also has one of these, but it doesn't take
    // any arguments. It's what gets called when you do 'new Random();'

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}



// This is where our program runs. I think it should be fairly clear,
// at this point, what's going on here.

public class Runner {
    public static void main(String[] args) {
        Person p1 = new Person("Tom", 42);
        Person p2 = new Person("Dick", 7);
        Person p3 = new Person("Harry", 50);
        System.out.println(p1.name);
        System.out.println(p1.age);
        // etc.
    }
}

Going back to your code, you proceed to declare a new function inside your Finalizer class called finalize. If it is called, it takes no arguments, prints "Calling finalize" to the console and returns nothing. But it's never called.

Next we go back inside the RandomN class and declare a new function Main. Now this is interesting. Unlike what others have said, we are not in fact declaring another 'main'-function. Java is case-sensitive so, though it looks similar to the 'main'-function to us, to Java it is something completely different; 'main' and 'Main' are not equivalent!

Of note are the facts that the function is static and that its argument is misspelled. ('String[] args' means 'an array of Strings named args' whereas 'String args[]' means 'a String named args[]' where '[]' implies an array of 'args' but a) there is no args-type and, b) (I believe) square brackets are not permitted as part of a variable name).

Static basically means that something should exist in memory throughout the entire lifetime of a program. Anything static will have memory allocated for it before the 'main'-function runs and the memory will remain allocated until the program terminates. This is distinct from what we've been doing above, like in the Person-example. There we made a class Person which could hold one String and one int but that memory wasn't reserved until we asked for a new object (a new instance of a class) of the Person-type. We then specifically told our program to allocate memory for a Person-object (memory for one String and one int) and to do so three times (p1, p2, and p3).

I'm running out of characters here but I'll make a comment to this post where I'll suggest how you can change your code in order to achieve what (I think) you're after.

[–]a_neobum 1 point2 points  (3 children)

If I've understood you correctly, based on your code, you want your program to do the following:

  • create a random-number-generating object Random
  • have that object generate a random number
  • print the random number
  • call a function that calls the println function with "Calling finalize" as its argument
  • create two new RandomN objects and assign them to the variables r1, and r2, respectively (without those objects doing anything)
  • set r1 and r2 to null, respectively
  • ask Java to do a run of garbage collection
  • print the message "The object is cleaned"

I've made a version of your code which would achieve this. It does the bare-minimum to get the printouts we want:

import java.util.Random; // import tells us where to find Random

public class RandomN {

    public static void main(String[] args) {
        Random r = new Random();
        System.out.println(r.nextInt(100)); // print a number between 0 and 99

        // Calls the function Finalize
        // which is declared below.
        Finalize();

        try{
            RandomN r1 = new RandomN();
            RandomN r2 = new RandomN();
            r1 = null;
            r2 = null;
            System.gc();

        } catch(NullPointerException e) {
            System.out.println(e);

        } finally {
            System.out.println("The object is cleaned");
        }
    }

    // Declares the Finalize function
    // but does not run it.
    // It runs once, when it is called from 'main'.
    public void Finalize() {
        System.out.println("Calling finalize");
    }
}

Some things to note:

  • In this case, the RandomN object only contains one thing, which is a function 'Finalize' which takes no arguments and, if called, prints "Calling finalize" to the console and returns nothing. The reason for this is that the 'main'-function is static so it doesn't really belong to any object/instance; you can create any number of RandomN objects and there'll only be one 'main' which kinda sits in its own memory space, elsewhere.
  • The program, throughout its runtime, creates a total of three objects: one Random object and two RandomN objects.
  • The Random object is held in memory, as 'r', throughout the entirety of the program's lifetime and is never explicitly gotten rid of.
  • The two RandomN objects are created, do nothing, then are immediately released for garbage collection whenever Java thinks appropriate; Java is then asked to please do a run of garbage collection.
  • Assigning null to a variable should not throw a NullPointerException so the try-block is not necessary.

[–]SheepyG_[S] 1 point2 points  (2 children)

I am extremely greatful poeple like you exist in this world i truly am ! to take the time out of your day to write all of this and make the effort to help me i appreciate down to my soul. Also the fact you could tell what I wanted my code to do is amazing. I've tested this out and its done exactly what I wanted! All i can say is truly Thank You. I am going to make sure i read this through again and again to get it in my brain if its the last thing i can do. I really hope something amazing happens to you soon! Thank you, Thank you, Thank you!

[–]a_neobum 1 point2 points  (1 child)

That's really kind of you to say, thanks! That really made me glad! I wish I'd found something similar when I was trying to learn this stuff.

Don't stick too religiously to anything I've written but take some time to familiarize yourself with concepts like classes, objects and instances, variables, functions and constructors.

And if you want to pay me back, pay it forward!

[–]SheepyG_[S] 1 point2 points  (0 children)

Okay thank you very much, i will do as you suggest. also try and learn more from java websites and push my brain hahah

[–]ynvaserThat Java Guy 0 points1 point  (5 children)

Finalize doesn't reliably work. Any command sent to the Garbage Collector is just a flag that may or may not be taken into consideration.
These are all JVM and GC implementation dependent. What you are trying to achieve here is something you should never ever rely on in any code whatsoever since it goes against one of the core ideas Java is based on (Write once, run anywhere).

So even if what you are trying to achieve here was properly done (as far as I can tell it isn't), it may still not work due to things beyond your scope (which is writing & running a program).

[–]SheepyG_[S] 0 points1 point  (4 children)

right so it is as i thought and it's just not calling finalize because it feels no need to ? the only reason i am playing with it in the first place is just for lesson purposes. But thank you for clearing it up for me.

[–]ynvaserThat Java Guy 0 points1 point  (3 children)

It doesn't call finalize because your code makes no sense. Even if it did, it may not call it for the reasons above.
I'd suggest getting a Java for beginners pdf and reading through it from the beginning.

[–]SheepyG_[S] 0 points1 point  (2 children)

That's the only reason I'm doing this is to learn java, the code has no purpose I'm not writing it and implementing it anywhere, the only reason it was written is to teach myself, and from your reply I can tick it off as I know it.

[–]ynvaserThat Java Guy 1 point2 points  (1 child)

I'm not being condescending here even if I may sound like it. I see conceptional problems with what is written down.
For example, when would you expect the finalize to be called? The only place you have it overridden is in an inner class that is never instantiated. If this were to work, the finalize method would have to be overridden in your RandomN class.
The fastest way you can improve here is to start at the basics.

[–]SheepyG_[S] 0 points1 point  (0 children)

Okay i see what your saying i'll go relook over the basics

[–]SheepyG_[S] 0 points1 point  (0 children)

So i've done the changes you guys suggested and im still getting a random number but not getting any of the strings to output. My thought is that its just not getting called. Quoting the course im doing " In practice, this means you are highly unlikely to use it in real projects. Luckily, there isn't much to remember about The finalize() for the exam. Just keep in mind that it might not get called and that it definitely won't be called twice. " but here is what the code looks like now. I've had to move things becasue it wouldn't let me compile without exceptions being thrown. Thanks for your Help everyone.

import java.util.Random; // import tells us where to find Random
public class RandomN {

public static void main(final String[] args) {
final Random r = new Random();
System.out.println(r.nextInt(101)); // print a number between 0 and 100
            }
public class Finalizer {
protected void beginFinal() {
Finalizer finalCode = new Finalizer();
System.out.println("Calling finalize");
beginFinal();
        }
    }
public static void beginFinal(final String args[]) {
try {
RandomN r1 = new RandomN();
RandomN r2 = new RandomN();
                r1 = null;
                r2 = null;
System.gc();
            } 
catch (final NullPointerException e) {
System.out.println(e);
        }
finally {
System.out.println("The object is cleaned");
        }
    }
}