Creating Objects Using Constructors

A class describes a generic template for creating, or instantiating, objects. In fact, an object must be instantiated before it can be used. To understand how to instantiate an object of a class and how to call methods of the class, you must know the API of a class, which the creators of the class make public. For example here.

Instantiating an object consists of defining an object reference—which will hold the address of the object in memory—and calling a special method of the class called a constructor, which has the same name as the class. The job of the constructor is to assign initial values to the data of the class.

The example below illustrates how to instantiate objects of the EndOfTimes class. Note that we store the EndOfTimes.java file in the same folder as Constructors.java.

Screen Shot 2018-12-19 at 3.40.07 PM.png

Notice that EndOfTimes is underlined red. That’s because it is not actually a known method of an API. The year 4.1 billion is also underlined red because it is sufficiently large to be out of range.

Declaring an object reference is very much like declaring a variable of a primitive type; you specify the data type and an identifier. For example, to declare an integer variable named number1, you provide the data type (int) and the identifier (number1), as follows:

Screen Shot 2018-12-19 at 3.43.56 PM

One notable difference in declaring an object reference is that its data type is a class, not a primitive data type. Here is the syntax for declaring an object reference:

Screen Shot 2018-12-19 at 3.46.17 PM

In the example above, lines 9, 12, and 14 declare object references for a EndOfTimes object. EndOfTimes, the class name, is the data type, and maitreya, kaliYuga, and ragnarok are the object references. Object references can refer to any object of its class. For example, EndOfTimes object references can point to any EndOfTimes object, but an EndOfTimes object reference cannot point to objects of other classes, such as a JapaneseStudent object. Once an object reference has been declared, you instantiate the object using the following syntax:

Screen Shot 2018-12-19 at 3.51.10 PM

This calls a constructor of the class to initialize the data. The argument list consists of a comma-separated list of initial data values to assign to the object. Classes often provide multiple constructors with different argument lists. Depending on which constructor you call, you can accept default values for the data or specify initial values for the data. When you instantiate an object, your argument list—that is, the number of arguments and their data types—must match one of the constructors’ argument lists.

The EndOfTimes class has a constructor. The constructor, EndOfTimes( ), is called the default constructor, because its argument list is empty. This constructor assigns default values to all data in the object. Thus, in line 14, which uses the default constructor, the data for the ragnarok object is set to the default values for the EndOfTimes class, whichever those may have been. Remember that API’s are designed by authors previously and you can then find them on websites such as the one linked above.

We also see another constructor for the EndOfTimes class, EndOfTimes( int mm, int dd, int yy ), takes three arguments, all of which should evaluate to integer values. The first argument is the value for the month, the second argument is the value for the day, and the third argument is the value for the year. Lines 10 and 12 of instantiate EndOfTimes objects using the second constructor. In line 10, the argument list tells the constructor to give the value 3 to the month, 26 to the day, and 2300 to the year. In line 12, the argument list tells the constructor to give the value 11 to the month, 4 to the day, and 4100000000 to the year (which is out of range).

Note that no data types are given in the argument list, only the initial values for the data. The data types of the arguments are specified in the API so that the client of the class knows what data types the constructor is expecting for its arguments. Lines 12 and 14 also illustrate that you can combine the declaration of the object reference and instantiation of the object in a single statement. When an object is instantiated, the JVM allocates memory to the new object. The object reference is assigned an address that the JVM uses to find that object in memory. The figure below shows one of the three objects instantiated in code above.

Screen Shot 2018-12-20 at 9.42.12 AM


It’s important to understand that an object reference and the object data are different: The object reference represents a memory location. Notice that the object references, maitreya, kaliYuga, and ragnarok, point to the locations of the object data.

 

Declaring Variables

A variable consists of a dual nature. It has a data type and a name.

Every variable must be given a name and a data type before it can be used. This is called declaring a variable. The syntax for declaring a variable is:

Screen Shot 2018-12-08 at 11.58.39 PM

or

Screen Shot 2018-12-09 at 4.00.02 PM

Note that a comma follows each identifier in the list except the last identifier, which is followed by a semicolon. By convention, the identifiers for variable names start with a lowercase letter. If the variable name consists of more than one word, then each word after the first should begin with a capital letter.

For example, these identifiers are conventional Java variable names: jewel3, specialRelativity, deathToNote, redInNovember, and xAxis.

Underscores conventionally are not used in variable names; they are reserved for the identifiers of constants, as we shall discuss in a later post.

Similarly, do not use dollar signs to begin variable names. The dollar sign is reserved for the first letter of programmatically generated variable names—that is, variable names generated by software, not people. Like with life in general, although arbitrariness may sound a disagreeable thing now, the value of following these conventions will become clearer as you gain more experience in Java and your programs become more complex.

 

Data Types, Variables, and Constants

In the previous blog post where we calculated the area of the last of the nine circles of hell, we used as data the value of PI and the radius, and found how large was Treachery. For each of these values, we assigned a name.

We also used the Java keyword double, which defines the data type of the data. The keyword double means that the value will be a floating-point number.

Java allows you to refer to the data in a program by defining variables, which are named locations in memory where you can store values. A variable can store one data value at a time, but that value might change as the program executes, and it might change from one execution of the program to the next. The real advantage of using variables is that you can name a variable, assign it a value, and subsequently refer to the name of the variable in an expression rather than hard-coding the specific value.

When we use a named variable, we need to tell the compiler which kind of data we will store in the variable. We do this by giving a data type for each variable. Java supports eight primitive data types: byte, short, int, long, float, double, char, and boolean. They are called primitive data types because they are part of the core Java language. The data type you specify for a variable tells the compiler how much memory to allocate and the format in which to store the data.

For example, if you specify that a data item is an int, then the compiler will allocate four bytes of memory for it and store its value as a 32-bit signed binary number. If, however, you specify that a data item is a double (a double-precision floating-point number), then the compiler will allocate 8 bytes of memory and store its value as an IEEE 754 floating-point number. Once you declare a data type for a data item, the compiler will monitor your use of that data item. If you attempt to perform operations that are not allowed for that type or are not compatible with that type, the compiler will generate an error.

Because the Java compiler monitors the operations on each data item, Java is called a strongly typed language. Take care in selecting identifiers for your programs. The identifiers should be meaningful and should reflect the data that will be stored in a variable, the concept encapsulated by a class, or the function of a method.

For example, the identifier age clearly indicates that the variable will hold an age. When you select meaningful variable names, the logic of your program is more easily understood, and you are less likely to introduce errors. Sometimes, it may be necessary to create a long identifier in order to clearly indicate its use, for example, numberOfPeopleSignedUpForCryonics. Although the length of identifiers is essentially unlimited, avoid creating extremely long identifiers because the longer the identifier, the more likely you are to make typos when entering the identifier into your program and the more it takes to type it, swallowing precious time. Finally, although it is legal to use identifiers, such as TRUE, which differ from Java keywords only in case, it isn’t a good idea because they easily can be confused with Java keywords, making the program logic less clear.

Writing the First Java Application

Here, you become initiated. Here, you create your first Java program. In the beginning was the static void, but here, with your own fingers, you create. This program prints the message, “Donate to SENS!” on the screen. Start by launching your IDE and open a new editor window. This is where you will write the code for the program. Before we type any code, however, let’s name the document. We do this by saving the document as IAmTheSavior.java. Be sure to capitalize the I, and the A, and the T, and the S, and keep the other letters lowercase. Java is case-sensitive, so Java considers iamthesavior.java or even Iamthesavior.java to be a different name.

Screen Shot 2018-12-07 at 7.02.36 PM

At this point, We ask that you type the program as you see it here. You are my mirror, and I create you in my image.

I’ll only give away a few secrets about the program now; additional details will unravel and become clear unto you in the following days.

Line numbers are not part of the program but are displayed to allow easy reference to a particular line in the code.

The first two lines, which start with two forward slashes, are comments. They will not be compiled or executed; they are simply information for the programmer and are used to leave notes that increase the readability of the program.

Line 4 defines the class name as IAmTheSavior. Notice that the class name must be spelled exactly the same way—including capitalization—as the file name, IAmTheSavior.java.

The curly braces in lines 5 and 12 mark the beginning and the end of the IAmTheSavior class, and the curly braces in lines 7 and 11 mark the beginning and the end of main.

Every Java application must define a class and a main method. Execution of a Java application always begins with the code inside main. So when this application begins, it will execute line 8, which writes the message “Donate to SENS!” to the system console.

Next, it executes line 10, System.exit( 0 ), which exits the program. Including this line is optional; if you omit this line, the application will exit normally. So it is just showing off my capacity to waste time or do things quickly. Never do unnecessary things.

As you type the program, notice that your IDE automatically colors your text to help you distinguish comments.

There are:

String literals: (“Donate to SENS!”),

Java class names: (String, System),

and keywords: (public, class, static), which are reserved for specific uses in Java.

Curly braces, brackets, and parentheses, which have syntactical meaning in Java, are sometimes displayed in color as well. Your IDE may use different colors instead of black as I have on Eclipse. When you have completed typing the code revealed to you in the image, compile it by going to wherever you see Run. If everything is typed correctly, the compiler will create an IAmTheSavior.class file, which contains the byte codes for the program. If you received any compiler errors, check that you have entered the code exactly as I have commanded. I will give you tips on finding and fixing the errors in the next section.

If you got a clean compile with no errors, you are worthy of this path! If not, then stop now and return from whence you came, for thee are destined to be but a kitchen-knave.

You’re ready to execute the application. This will invoke the JVM and pass it the IAmTheSavior.class file created by the compiler. If God’s in his heaven and all is right in the world, you will see the message, Donate to SENS!, displayed on the Java console, which is the text window that opens automatically.

This is the correct output of the program:

Screen Shot 2018-12-07 at 7.36.54 PM

If the compiler found syntax errors in the code, these are called compiler errors, not because the compiler caused them, but because the compiler found them. When the compiler detects errors in the code, it writes diagnostic information about the errors. For example, try typing println with a capital P (as Println), and recompiling.

The compiler displays the following message:

Screen Shot 2018-12-07 at 7.42.54 PM

Before you compile wrongly, you are allowed to know about your error in the source code, and where the error occurred:

Screen Shot 2018-12-07 at 7.45.46 PM

 

In this case, the error occurred on line 8. The red dashed underlining points to Println as being the cause of the error. The symbol and location information in the third and fourth lines indicate that the Println method is unknown. Remember that Java is case-sensitive, so println and Println are considered to be different. As you gain experience with Java, these error messages will become more meaningful to you.

With the Eclipse IDE, clicking on the red rectangle on the right transfers you to the source of the error on that line, so you can correct the error:

Screen Shot 2018-12-07 at 7.53.33 PM

 

Many times, the compiler will find more than one error in the source code. When that happens, DON’T PANIC! Often, a simple problem, such as a missing semicolon or curly brace, can cause multiple compiler errors.

For example, after correcting the preceding error, try deleting the left curly brace in line 7, then recompiling.

Screen Shot 2018-12-08 at 7.43.05 AM

The compiler reports this error:

Screen Shot 2018-12-07 at 7.58.44 PM

As you can see, the compiler message reports the problem exactly. If it does not, then looking at the surrounding lines will often help you find the error. Depending on your IDE, you might see another message than what is shown here because some IDEs don’t attempt to interpret the error messages from the compiler. Eclipse does, and this allows you to be provided with more relevant information on the errors.

It is best to fix the errors using an IDE, if you wrote the code into a text editor and had to gamble a compile each time – fixing one problem at a time – this would cause you to waste your existence in some sense.

When all the compiler errors are corrected, you’re ready to execute the program. It is possible to get be told you are clean by the IDE, but yet still get an error when attempting to run the program. To demonstrate this, try eliminating the brackets in line 6 after the word String:

Screen Shot 2018-12-08 at 7.58.39 AM

No errors are reported. But when you try to run the program, instead of Donate to SENS!, the following error message is displayed:

Screen Shot 2018-12-08 at 8.00.13 AM

This means that the main method header (line 6) was not typed correctly. Thus, we’ve seen that two types of errors can occur while you are developing a Java program: compiler errors, which are usually caused by language syntax errors or misspellings, and run-time errors, which are often caused by problems using the prewritten classes. Run-time errors can also be caused by exceptions that the JVM detects as it is running, such as an attempt to divide by zero.

Because one syntax error can cause multiple compiler errors, correct only the obvious errors and recompile after each correction.

Once your program compiles cleanly and executes without run-time errors, you may be tempted to conclude that your task is over. Far from it—you must also verify the results, or output, of the program.

Screen Shot 2018-12-08 at 8.18.35 AM

In the sample program, it’s difficult to get incorrect results—other than misspelling the message or omitting the spaces between the words. But any nontrivial program should be tested thoroughly before declaring it production-ready. To test a program, use your intuition to consider the relevant possible inputs and the corresponding correct outputs that result. It isn’t feasible to test every possible input, so programmers usually test boundary conditions, which are the values that sit on the boundaries of producing different output for a program.

Interestingly, we exist in a multiverse if we are empiricists with regard to the probability amplitude of the universal wavefunction. We then get a handle on probability amplitude with a complex conjugate:

i ± 1

The reason we represent reality with a complex conjugate is because all variables are conjugated – the more you know about momentum, the less you know about position. However, there is no little electron zipping around, or occipital lobes trying to catch it, it’s conjugated variables all the way up and all the way down.

Staring at the probability amplitude represented in complex conjugates suggests that infinity contains equal amounts of good and evil – undifferentiated chaos.

However, experiment reveals that some things are more likely than others. This causes us to take the squared modulus of the complex conjugate, hence invoking rough bounds that chain infinity and guide our being:

|i ± 1|²

This is the probability density that says, “look here, not there.”

Hydrogen_Density_Plots.png

Say you have a problem, or perhaps a curiosity – you want to test the code that determines whether an integer is negative or nonnegative. In order to find out the answer, you must submit the program offerings of both −1 and 0, so that it may feed on them. These chosen numbers exist at the very edges of negative and nonnegative integers, and hence form their boundaries. In other words, the unbridgeable fault-line between negative and nonnegative integers is between −1 and 0.

When a program does not produce the correct output, we say the program contains logic errors. By testing your program thoroughly, you can discover and correct all logic errors. The grey table above shows types of program errors and their usual causes. We’ll talk more about testing techniques here on Vitrify Her.

 

 

 

Pseudocode

You might associate the word pseudo with a sham. But when developing a programmer mindset, we try to eliminate as many aesthetic smells that concepts carry. Pseudo comes from the Greek, pseudes, which means “false.” But the reason we call it pseudocode is because it is not the full expression of the code – the code that actually runs; it is rather like the skeleton. It should instead be called skeletoncode, and it is a method for expressing a program’s order of instructions in the spoken language, rather than a programming language.

In this way, the programmer can concentrate on designing a program without also being slowed down by immediately converting to the syntax of the particular programming language. This is the same as when drawing. When drawing a human we first draft a faceless model. The pseudocode for calculating the sum of two numbers would look like this:

Screen Shot 2018-12-07 at 1.07.15 PM

There are no rules. You can use any wording that works for you.

Let’s look at another example. Suppose your program needs to calculate the square root of an integer. The instructions for calculating a square root are rather complex; gracefully and compassionately, Java provides prewritten code that computes the square root of any integer. The prewritten code is called a method, and your program can execute that code by calling the method. As part of the method call, you tell the method which integer’s square root you want to calculate. This is called passing an argument to the method. When the method finishes executing its instructions, control is passed back to your program just after the method call.

Another way of looking at method calls is to consider what happens when you’re walking through a night-lit city and find a restaurant with an aroma that lures you in. Your brain marks your place in the night-lit city trajectory and goes to eat inside the restaurant. When you’re finished dining on the meal, you go back to the streets and continue walking.

Here I show the pseudocode for calculating the square root of an integer:

Screen Shot 2018-12-07 at 1.30.37 PM

The order of operations is still input, calculate, and output, but we’re calling a method to perform the calculation for us. Now suppose your task is to determine whether a number is positive or negative. First, your program should input the number into the computer. Next, you need to determine whether the number is positive or negative. You know that numbers greater than or equal to 0 are positive and numbers less than 0 are negative, so your program should compare the number to 0. Finally, your program should write a message indicating whether the number is positive or negative.

Like in the pseudocode examples, the operations are input, calculate, and output, in that order. However, depending on whether the number is positive or negative, your program should write a different message. If the number is greater than or equal to 0, the program should write a message that the number is positive (may the God of Mathematics forgive this sin), but if the number is less than 0, the program should write a message that the number is negative. Code used to handle this situation is called selection; the program selects which code to execute based on the value of the data.

The pseudocode for this program could be written as that shown:

Screen Shot 2018-12-07 at 1.33.44 PM

Notice the indentation for the code that will be selected based on the comparison of the number with 0. Programmers use indentation to make it easier to see the flow of control of the program.

Now let’s get a little more complicated. Suppose your program needs to find the sum of a group of numbers. This is called accumulating. To accomplish this, we can take the same approach as if we were adding a group of numbers using a calculator. We start with a total of 0 and add each number, one at a time, to the running total. When we have no more numbers to add, the running total is the total of all the numbers. Translating this into pseudocode, we get the code shown:

Screen Shot 2018-12-07 at 1.37.31 PM

The indented code will be repeated for each number read until there are no more numbers. This repeated execution of the same code is called looping, or iteration, and is used extensively in programming whenever the same processing needs to be performed on each item in a set.

Accumulating a total and determining whether a number is positive or negative are just two of many commonly performed operations. In programming, you will often perform tasks for which there are standard methods of processing, called algorithms. For example, the algorithm for accumulation is to set a total to 0, use looping to add each item to the total, then output the total. More generally, you can think of an algorithm as a strategy to solve a problem. You yourself are a strategy to solve a problem in the multiverse, a timeless algorithm. However, knowing the full nature of the problem would not allow you to solve it – this would be equivalent to having already solved it – hence becoming permanently stuck at a local maxima. The human mind is set up to be deceived about where it is going.

In an earlier post, we used an algorithm to convert a decimal number to its binary representation. Other common programming tasks are counting items, calculating an average, sorting items into order, and finding the minimum and maximum values. Here on Vitrify Her, you will learn the standard algorithms for performing these common operations. Once you learn these algorithms, your ability to achieve synchronization will become easier. When you recognize that a program requires these tasks, you can simply plug in the appropriate algorithm with some minor modifications.

Programming, in large part, is simply reducing a complex task to a set of subtasks that can be implemented by artistically combining the Four Noble Algorithmic Truths: sequential processing, method calls, selection, and looping. The most difficult part of programming, however, is recognizing which algorithms to apply to the problem at hand. This requires analytical skills and the ability to see patterns. Here on Vitrify Her, I will point out common patterns wherever possible.

Looking for patterns will help you determine the appropriate algorithms for your programs. Looking for patterns is the way of sunyata.

Programming Basics

In many ways, programming is like solving a puzzle. You have a task to perform and you know the operations that a computer can perform (input, calculations, comparisons, rearranging of items, and output). As a programmer, your job is to decompose a task into individual, ordered steps of inputting, calculating, comparing, rearranging, and outputting. For example, suppose your task is to find the sum of two numbers. First, your program needs to read (input) the numbers into the computer. Next, your program needs to add the two numbers together (calculate). Finally, your program needs to write (output) the sum. Notice that this program consists of steps, called instructions, which are performed in order (“First,” “Next,” “Finally”). In physical reality outside of Mind, time doesn’t exist because of relativity of simultaneity (simultaneous events in one frame of reference are not simultaneous in another). So the very sense of sequential instructions occurring is a local phenomena in the broader eternity.

Screen Shot 2018-11-21 at 8.43.53 PM

Performing operations in order, one after another, is called sequential processing. The order in which instructions are executed by the computer is critical in programming. You can’t calculate the sum of two numbers before you have read the two numbers, and you can’t output a sum before you have calculated it. Programming, therefore, requires the programmer to specify the ordering of instructions, which is called the flow of control of the program. This often leads to the confused notion that if intelligence was involved in our fate, that it too must exist in the past light cone, in order to set things in motion. However, this is a projection fallacy from the map to the territory. The binding into experience occurs from, relativistic, and therefore eternal, “pieces.” The pieces are actually not even pieces at all, which somehow exist outside of Mind. Experiment reveals that only probability amplitude exists, which Mind then chooses to constrain with the squared modulus. Under plausible assumption that the multiverse is real and that intelligence scales up far past the human imagination, then we are already inside the most intelligent process.

I have now exposed you to one of the Four Noble Truths in the path to control the flow of the program: sequential execution. The other three are method call, selection, and looping. Be mindful, oh bhikhu, of sequential execution, and we’ll discuss the other types of flow of control in a following blog post. Since mastering the flow of control is essential to getting a program to produce correct output, programmers use a tool called pseudocode to help them design the flow of control before writing the code, just in the same way that My non-adaptive drafts in Hilbert Space become mangled into you.