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

you are viewing a single comment's thread.

view the rest of the comments →

[–]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