Before you mod, you should have at least a basic understanding of how Java works, and the basic syntax of methods and classes. This will be a large expansion of text-based Java tutorials that will help prepare you for venturing into the world of modding. This will help with jbond98's modding tutorials.
This will be in multiple parts, ranging from the basics to advanced topics.
ALL of these tutorials will be done under Java 6, although they should all work correctly if you have Java 7 installed on your computer. I will not be teaching you how to set up your IDE and download the correct JDK, you should have those as prerequisites already. Most of these are from Oracle's tutorials, but I moved some here for easy access.
Each category, (Basic, Beginner, Intermediate, Advanced, User Requests), will be separated. Also, note that the Basic tutorials will be mostly reading and conceptual ideas that are central in Java.
-------------------------------------- Data Types: --------------------------------------
The Java programming language is statically-typed, which means that all variables must first be declared before they can be used. This involves stating the variable's type and name, as you've already seen:
int cpus = 1;
Doing so tells your program that a field named "cpus" exists, holds numerical data, and has an initial value of "1". A variable's data type determines the values it may contain, plus the operations that may be performed on it. In addition to int, the Java programming language supports seven other primitive data types. A primitive type is predefined by the language and is named by a reserved keyword. Primitive values do not share state with other primitive values. The eight primitive data types supported by the Java programming language are:
boolean
The boolean data type has only two possible values: true and false. Use this data type for simple flags that track true/false conditions. This data type represents one bit of information, but its "size" isn't something that's precisely defined.
byte
The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive). The byte data type can be useful for saving memory in large arrays, where the memory savings actually matters. They can also be used in place of int where their limits help to clarify your code; the fact that a variable's range is limited can serve as a form of documentation.
short
The short data type is a 16-bit signed two's complement integer. It has a minimum value of -32,768 and a maximum value of 32,767 (inclusive). As with byte, the same guidelines apply: you can use a short to save memory in large arrays, in situations where the memory savings actually matters.
int
The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive). For integral values, this data type is generally the default choice unless there is a reason (like the above) to choose something else. This data type will most likely be large enough for the numbers your program will use, but if you need a wider range of values, use long instead.
long
The long data type is a 64-bit signed two's complement integer. It has a minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807 (inclusive). Use this data type when you need a range of values wider than those provided by int.
float
The float data type is a single-precision 32-bit IEEE 754 floating point. Its range of values is beyond the scope of this discussion, but is specified in the Floating-Point Types, Formats, and Values section of the Java Language Specification. As with the recommendations for byte and short, use a float (instead of double) if you need to save memory in large arrays of floating point numbers. This data type should never be used for precise values, such as currency. For that, you will need to use the java.math.BigDecimal class instead. Numbers and Strings covers BigDecimal and other useful classes provided by the Java platform.
double
The double data type is a double-precision 64-bit IEEE 754 floating point. Its range of values is beyond the scope of this discussion, but is specified in the Floating-Point Types, Formats, and Values section of the Java Language Specification. For decimal values, this data type is generally the default choice. As mentioned above, this data type should never be used for precise values, such as currency.
char
The char data type is a single 16-bit Unicode character. It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive).
String
In addition to the eight primitive data types listed above, the Java programming language also provides special support for character strings via the java.lang.String class. Enclosing your character string within double quotes will automatically create a new String object; for example, String s = "this is a string";. String objects are immutable, which means that once created, their values cannot be changed. The String class is not technically a primitive data type, but considering the special support given to it by the language, you'll probably tend to think of it as such. You'll learn more about the String class in Simple Data Objects
In the Java programming language, the terms "field" and "variable" are both used; this is a common source of confusion among new developers, since both often seem to refer to the same thing.
The Java programming language defines the following kinds of variables:
Local
Similar to how an object stores its state in fields, a method will often store its temporary state in local variables. The syntax for declaring a local variable is similar to declaring a field (for example, int count = 0;). There is no special keyword designating a variable as local; that determination comes entirely from the location in which the variable is declared — which is between the opening and closing braces of a method. As such, local variables are only visible to the methods in which they are declared; they are not accessible from the rest of the class.
Instance
Technically speaking, objects store their individual states in "non-static fields", that is, fields declared without the static keyword. Non-static fields are also known as instance variables because their values are unique to each instance of a class (to each object, in other words); the currentSpeed of one computer is independent from the currentSpeed of another.
Class
A class variable is any field declared with the static modifier; this tells the compiler that there is exactly one copy of this variable in existence, regardless of how many times the class has been instantiated. A field defining the number of CPUs for a particular kind of computer could be marked as static since conceptually the same number of CPUs will apply to all instances. The code static int numCPUs = 6; would create such a static field. Additionally, the keyword final could be added to indicate that the number of CPUs will never change.
Parameter
You've already seen examples of parameters, in the Computer class. Recall that the signature for the main method is public static void main(String[] args). Here, the args variable is the parameter to this method. The important thing to remember is that parameters are always classified as "variables" not "fields". This applies to other parameter-accepting constructs as well (such as constructors and exception handlers) that you'll learn about later in the tutorial.
Having said that, the remainder of this tutorial uses the following general guidelines when discussing fields and variables. If we are talking about "fields in general" (excluding local variables and parameters), we may simply say "fields". If the discussion applies to "all of the above", we may simply say "variables". If the context calls for a distinction, we will use specific terms (static field, local variables, etc.) as appropriate. You may also occasionally see the term "member" used as well. A type's fields, methods, and nested types are collectively called its members.
Every programming language has its own set of rules and conventions for the kinds of names that you're allowed to use, and the Java programming language is no different. The rules and conventions for naming your variables can be summarized as follows:
Variable names are case-sensitive. A variable's name can be any legal identifier — an unlimited-length sequence of Unicode letters and digits, beginning with a letter, the dollar sign "$", or the underscore character "_". The convention, however, is to always begin your variable names with a letter, not "$" or "_". Additionally, the dollar sign character, by convention, is never used at all. You may find some situations where auto-generated names will contain the dollar sign, but your variable names should always avoid using it. A similar convention exists for the underscore character; while it's technically legal to begin your variable's name with "_", this practice is discouraged. White space is not permitted.
Subsequent characters may be letters, digits, dollar signs, or underscore characters. Conventions (and common sense) apply to this rule as well. When choosing a name for your variables, use full words instead of cryptic abbreviations. Doing so will make your code easier to read and understand. In many cases it will also make your code self-documenting; fields named cadence, speed, and gear, for example, are much more intuitive than abbreviated versions, such as s, c, and g. Also keep in mind that the name you choose must not be a keyword or reserved word.
If the name you choose consists of only one word, spell that word in all lowercase letters. If it consists of more than one word, capitalize the first letter of each subsequent word. The names cpuRatio and currentCPU are prime examples of this convention. If your variable stores a constant value, such as static final int NUM_CPUS = 6, the convention changes slightly, capitalizing every letter and separating subsequent words with the underscore character. By convention, the underscore character is never used elsewhere.
It's not always necessary to assign a value when a field is declared. Fields that are declared but not initialized will be set to a reasonable default by the compiler. Generally speaking, this default will be zero or null, depending on the data type. Relying on such default values, however, is generally considered bad programming style.
The following chart summarizes the default values for the above data types.
Data Type | Default Value (for fields)
byte | 0
short |0
int |0
long |0L
float |0.0f
double |0.0d
char |'\u0000'
String (or any object) | null
boolean | false
Local variables are slightly different; the compiler never assigns a default value to an uninitialized local variable. If you cannot initialize your local variable where it is declared, make sure to assign it a value before you attempt to use it. Accessing an uninitialized local variable will result in a compile-time error.
In real life, you'll find many instances of a specific object. For example, computers. All computers do the fundamentally same thing, but they have different specific parts. Each computer is built from blueprints, and then slightly modified to fit the user's needs. In object-oriented terms, we say that your computer is an instance of the class of objects known as computers. A class is the blueprint from which individual objects are created.
For example, look at the following. (You do not need to be able to understand it, just read it)
class Computer {
int numOfScreens = 1;
int numOfGPUs = 1;
int clockSpeed = 3;
public void checkScreens(int numOfScreens) {
numOfScreens = newValue;
}
public void clockGPUs(int numOfGPUs) {
int newSpeed = numOfGPUs + 1 * clockSpeed;
System.out.println(newSpeed);
}
}
The syntax will look alien, but it's really not that bad. The fields numOfScreens, numOfGPUs, and clockSpeed represent the Object's state, and the methods checkSums and clockGPUs define it's interactions with other classes and objects. This code, on it's own, does not run, as it does not contain the main() method. This is just a blueprint for each computer you want to run. It's the responsibility of creating and using new Computer objects belongs to some different class in your application.
Here's an example that WILL run:
class ComputerDemo {
public static void main(String[] args) {
//Create two different Computer Objects
Computer com1 = new Computer();
Computer com2 = new Computer();
//Invoke methods on these objects
com1.clockGPUs(100);
com2.clockGPUs(321);
}
}
This code, combined with the example above, will run. Look in the console to see what it prints.
Objects are the fundemental basics of Java. Java is an object oreinted language, and deals with objects. Objects have state and behavior. The State of an object are all of the variables and their values that are set within the object's class. It's behavior are the methods you program into it to allow it to function in your program or mod.
For example, say you have a Dog object. It has multiple states. Breed, gender, height, width are all states of the Dog object, for example. The dog object also has a few behaviors, or methods. It can bark(), run(), chaseCat() and eat(). The states (variables) all affect what the object can, or cannot do.
Objects have 4 main benefits:
Modularity: The source code for the object can be maintained without fear of messing up any existing code, and can be passed around the program easily.
Information-Hiding: Because you only interact directly with methods, the internal structure of how things work is hidden from the outside world, or any plugins that are created, unless you want it to be seen.
Re-Usable Code: If the object already exists in the code, or is written by someone else, you can use it in your program. This allows you to only write what you absolutely need, and not more.
Plug, chug, and debug: If something you write turns out to be bad or problematic, you can simply remove it, and plug in a default dummy object or method in it's place. If something breaks in Runtime, it's easily fixable.
Different kinds of objects often have things in common with others. Gaming computers, general computers, and work computer all are computers, but have slightly different things about them. Gaming computers are high quality, regular computers are regular, and work computers are ergonomic. Object oriented programming allows classes and objects to inherit other objects properties. There would be a Superclass Computer, with the subclasses of gaming, regular, and work computers, as they have specific functions.
The syntax for doing this is simple.
class GamingComputer extends Computer {
//new fields and methods defining a gaming computer
}
This gives GamingComputer all of the same fields and methods as Computer, but allows the class to only focus on exactly what makes it different. This makes the code very easy and simple to read. You must take care to make sure that you document your files, otherwise it will be horrendously confusing to the programmers that you work with. The superclass code will not appear in the subclass directly, but will be useable.
Packages are quite simple. Think of them as a folder. You have a folder for the GUI code, a folder for the sound code, and a folder for the network code. Each of those "folders" are packages. They allow the coders to be able to quickly identify different parts of the code.
You may have noticed that the new keyword isn't used when initializing a variable of a primitive type. Primitive types are special data types built into the language; they are not objects created from a class. A literal is the source code representation of a fixed value; literals are represented directly in your code without requiring computation. As shown below, it's possible to assign a literal to a variable of a primitive type:
boolean result = true;
char capitalC = 'C';
byte b = 100;
short s = 10000;
int i = 100000;
Integer Literals:
An integer literal is of type long if it ends with the letter L or l; otherwise it is of type int. It is recommended that you use the upper case letter L because the lower case letter l is hard to distinguish from the digit 1.
Values of the integral types byte, short, int, and long can be created from int literals. Values of type long that exceed the range of int can be created from long literals. Integer literals can be expressed by these number systems:
Decimal: Base 10, whose digits consists of the numbers 0 through 9; this is the number system you use every day
Hexadecimal: Base 16, whose digits consist of the numbers 0 through 9 and the letters A through F
Binary: Base 2, whose digits consists of the numbers 0 and 1 (you can create binary literals in Java SE 7 and later)
For general-purpose programming, the decimal system is likely to be the only number system you'll ever use. However, if you need to use another number system, the following example shows the correct syntax. The prefix 0x indicates hexadecimal and 0b indicates binary:
// The number 26, in decimal
int decVal = 26;
// The number 26, in hexadecimal
int hexVal = 0x1a;
// The number 26, in binary
int binVal = 0b11010;
Floating-Point Literals:
A floating-point literal is of type float if it ends with the letter F or f; otherwise its type is double and it can optionally end with the letter D or d.
The floating point types (float and double) can also be expressed using E or e (for scientific notation), F or f (32-bit float literal) and D or d (64-bit double literal; this is the default and by convention is omitted).
double d1 = 123.4;
// same value as d1, but in scientific notation
double d2 = 1.234e2;
float f1 = 123.4f;
Character and String Literals:
Literals of types char and String may contain any Unicode (UTF-16) characters. If your editor and file system allow it, you can use such characters directly in your code. If not, you can use a "Unicode escape" such as '\u0108' (capital C with circumflex), or "S\u00ED Se\u00F1or" (Sí Señor in Spanish). Always use 'single quotes' for char literals and "double quotes" for String literals. Unicode escape sequences may be used elsewhere in a program (such as in field names, for example), not just in char or String literals.
The Java programming language also supports a few special escape sequences for char and String literals: \b (backspace), \t (tab), \n (line feed), \f (form feed), \r (carriage return), \" (double quote), \' (single quote), and \\ (backslash).
There's also a special null literal that can be used as a value for any reference type. null may be assigned to any variable, except variables of primitive types. There's little you can do with a null value beyond testing for its presence. Therefore, null is often used in programs as a marker to indicate that some object is unavailable.
Class Literal:
Finally, there's also a special kind of literal called a class literal, formed by taking a type name and appending ".class"; for example, String.class. This refers to the object (of type Class) that represents the type itself.
Using Underscore Characters in Numeric Literals:
In Java SE 7 and later, any number of underscore characters (_) can appear anywhere between digits in a numerical literal. This feature enables you, for example. to separate groups of digits in numeric literals, which can improve the readability of your code.
For instance, if your code contains numbers with many digits, you can use an underscore character to separate digits in groups of three, similar to how you would use a punctuation mark like a comma, or a space, as a separator.
The following example shows other ways you can use the underscore in numeric literals:
long creditCardNumber = 1234_5678_9012_3456L;
long socialSecurityNumber = 999_99_9999L;
float pi = 3.14_15F;
long hexBytes = 0xFF_EC_DE_5E;
long hexWords = 0xCAFE_BABE;
long maxLong = 0x7fff_ffff_ffff_ffffL;
byte nybbles = 0b0010_0101;
long bytes = 0b11010010_01101001_10010100_10010010;
You can place underscores only between digits; you cannot place underscores in the following places:
At the beginning or end of a number
Adjacent to a decimal point in a floating point literal
Prior to an F or L suffix
In positions where a string of digits is expected
The following examples demonstrate valid and invalid underscore placements (which are highlighted) in numeric literals:
// Invalid: cannot put underscores
// adjacent to a decimal point
float pi1 = 3_.1415F;
// Invalid: cannot put underscores
// adjacent to a decimal point
float pi2 = 3._1415F;
// Invalid: cannot put underscores
// prior to an L suffix
long socialSecurityNumber1 = 999_99_9999_L;
// This is an identifier,
//not a numeric literal
int x1 = _52;
// OK (decimal literal)
int x2 = 5_2;
// Invalid: cannot put underscores
// At the end of a literal
int x3 = 52_;
// OK (decimal literal)
int x4 = 5_______2;
// Invalid: cannot put underscores
// in the 0x radix prefix
int x5 = 0_x52;
// Invalid: cannot put underscores
// at the beginning of a number
int x6 = 0x_52;
// OK (hexadecimal literal)
int x7 = 0x5_2;
// Invalid: cannot put underscores
// at the end of a number
int x8 = 0x52_;
An array is a container object that holds a fixed number of values of a single type. The length of an array is established when the array is created. After creation, its length is fixed.
Each item in an array is called an element, and each element is accessed by its numerical index. As shown in the above illustration, numbering begins with 0. The 9th element, for example, would therefore be accessed at index 8.
The following program, ArrayDemo, creates an array of integers, puts some values in it, and prints each value to standard output.
class ArrayDemo {
public static void main(String[] args) {
// declares an array of integers
int[] anArray;
// allocates memory for 10 integers
anArray = new int[10];
// initialize first element
anArray[0] = 100;
// initialize second element
anArray[1] = 200;
// etc.
anArray[2] = 300;
anArray[3] = 400;
anArray[4] = 500;
anArray[5] = 600;
anArray[6] = 700;
anArray[7] = 800;
anArray[8] = 900;
anArray[9] = 1000;
System.out.println("Element at index 0: "
+ anArray[0]);
System.out.println("Element at index 1: "
+ anArray[1]);
System.out.println("Element at index 2: "
+ anArray[2]);
System.out.println("Element at index 3: "
+ anArray[3]);
System.out.println("Element at index 4: "
+ anArray[4]);
System.out.println("Element at index 5: "
+ anArray[5]);
System.out.println("Element at index 6: "
+ anArray[6]);
System.out.println("Element at index 7: "
+ anArray[7]);
System.out.println("Element at index 8: "
+ anArray[8]);
System.out.println("Element at index 9: "
+ anArray[9]);
}
}
The output from this program is:
Element at index 0: 100
Element at index 1: 200
Element at index 2: 300
Element at index 3: 400
Element at index 4: 500
Element at index 5: 600
Element at index 6: 700
Element at index 7: 800
Element at index 8: 900
Element at index 9: 1000
In a real-world programming situation, you'd probably use one of the supported looping constructs to iterate through each element of the array, rather than write each line individually as shown above. However, this example clearly illustrates the array syntax.
The above program declares anArray with the following line of code:
// declares an array of integers
int[] anArray;
Like declarations for variables of other types, an array declaration has two components: the array's type and the array's name. An array's type is written as type[], where type is the data type of the contained elements; the square brackets are special symbols indicating that this variable holds an array. The size of the array is not part of its type (which is why the brackets are empty). An array's name can be anything you want, provided that it follows the rules and conventions as previously discussed in the naming section. As with variables of other types, the declaration does not actually create an array — it simply tells the compiler that this variable will hold an array of the specified type.
You can also place the square brackets after the array's name:
// this form is discouraged
float anArrayOfFloats[];
However, convention discourages this form; the brackets identify the array type and should appear with the type designation.
One way to create an array is with the new operator. The next statement in the ArrayDemo program allocates an array with enough memory for ten integer elements and assigns the array to the anArray variable.
// create an array of integers
anArray = new int[10];
If this statement were missing, the compiler would print an error like the following, and compilation would fail:
ArrayDemo.java:4: Variable anArray may not have been initialized.
The next few lines assign values to each element of the array:
anArray[0] = 100; // initialize first element
anArray[1] = 200; // initialize second element
anArray[2] = 300; // etc.
Each array element is accessed by its numerical index:
System.out.println("Element 1 at index 0: " + anArray[0]);
System.out.println("Element 2 at index 1: " + anArray[1]);
System.out.println("Element 3 at index 2: " + anArray[2]);
Alternatively, you can use the shortcut syntax to create and initialize an array:
Here the length of the array is determined by the number of values provided between { and }.
You can also declare an array of arrays (also known as a multidimensional array) by using two or more sets of square brackets, such as String[][] names. Each element, therefore, must be accessed by a corresponding number of index values.
In the Java programming language, a multidimensional array is simply an array whose components are themselves arrays. This is unlike arrays in C or Fortran. A consequence of this is that the rows are allowed to vary in length, as shown in the following MultiDimArrayDemoprogram:
class MultiDimArrayDemo {
public static void main(String[] args) {
String[][] names = {
{"Mr. ", "Mrs. ", "Ms. "},
{"Smith", "Jones"}
};
// Mr. Smith
System.out.println(names[0][0] + names[1][0]);
// Ms. Jones
System.out.println(names[0][2] + names[1][1]);
}
}
The output from this program is:
Mr. Smith
Ms. Jones
Finally, you can use the built-in length property to determine the size of any array. The code
System.out.println(anArray.length);
will print the array's size to standard output.
The System class has an arraycopy method that you can use to efficiently copy data from one array into another:
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
The two Object arguments specify the array to copy from and the array to copy to. The three int arguments specify the starting position in the source array, the starting position in the destination array, and the number of array elements to copy.
The following program, ArrayCopyDemo, declares an array of char elements, spelling the word "decaffeinated". It uses arraycopy to copy a subsequence of array components into a second array:
-------------------------------------- Expressions, Statements, and Blocks: --------------------------------------
It's time to learn about expressions, statements, and blocks. Operators may be used in building expressions, which compute values; expressions are the core components of statements; statements may be grouped into blocks.
An expression is a construct made up of variables, operators, and method invocations, which are constructed according to the syntax of the language, that evaluates to a single value.
int cadence = 0;
anArray[0] = 100;
System.out.println("Element 1 at index 0: " + anArray[0]);
int result = 1 + 2; // result is now 3
if (value1 == value2)
System.out.println("value1 == value2");
The data type of the value returned by an expression depends on the elements used in the expression. The expression cadence = 0 returns an int because the assignment operator returns a value of the same data type as its left-hand operand; in this case, cadence is an int. As you can see from the other expressions, an expression can return other types of values as well, such as boolean or String.
The Java programming language allows you to construct compound expressions from various smaller expressions as long as the data type required by one part of the expression matches the data type of the other. Here's an example of a compound expression:
1 * 2 * 3
In this particular example, the order in which the expression is evaluated is unimportant because the result of multiplication is independent of order; the outcome is always the same, no matter in which order you apply the multiplications. However, this is not true of all expressions. For example, the following expression gives different results, depending on whether you perform the addition or the division operation first:
x + y / 100 // ambiguous
You can specify exactly how an expression will be evaluated using balanced parenthesis: ( and ). For example, to make the previous expression unambiguous, you could write the following:
(x + y) / 100 // unambiguous, recommended
If you don't explicitly indicate the order for the operations to be performed, the order is determined by the precedence assigned to the operators in use within the expression. Operators that have a higher precedence get evaluated first. For example, the division operator has a higher precedence than does the addition operator. Therefore, the following two statements are equivalent:
x + y / 100
x + (y / 100) // unambiguous, recommended
When writing compound expressions, be explicit and indicate with parentheses which operators should be evaluated first. This practice makes code easier to read and to maintain.
Statements are roughly equivalent to sentences in natural languages. A statement forms a complete unit of execution. The following types of expressions can be made into a statement by terminating the expression with a semicolon ( .
In addition to expression statements, there are two other kinds of statements: declaration statements and control flow statements. A declaration statement declares a variable. You've seen many examples of declaration statements already:
Finally, control flow statements regulate the order in which statements get executed.
A block is a group of zero or more statements between balanced braces and can be used anywhere a single statement is allowed. The following example, BlockDemo, illustrates the use of blocks:
class BlockDemo {
public static void main(String[] args) {
boolean condition = true;
if (condition) { // begin block 1
System.out.println("Condition is true.");
} // end block one
else { // begin block 2
System.out.println("Condition is false.");
} // end block 2
}
}
-------------------------------------- If and Else: --------------------------------------
The if-then statement is the most basic of all the control flow statements. It tells your program to execute a certain section of code only if a particular test evaluates to true. One possible implementation of the turnonGPU method could be as follows:
void turnonGPU {
// the "if" clause: GPU must be on
if (isRunning){
// the "then" clause: increase ison by 1
ison1++;
}
}
If this test evaluates to false (meaning that the GPU not running), control jumps to the end of the if-then statement.
In addition, the opening and closing braces are optional, provided that the "then" clause contains only one statement:
void turnonGPU() {
// same as above, but without braces
if (ison)
ison1++;
}
Deciding when to omit the braces is a matter of personal taste. Omitting them can make the code more brittle. If a second statement is later added to the "then" clause, a common mistake would be forgetting to add the newly required braces. The compiler cannot catch this sort of error; you'll just get the wrong results.
The if-then-else statement provides a secondary path of execution when an "if" clause evaluates to false. You could use an if-then-else statement in the isGPUOn method to take some action if the whatevers are applied when the GPU is not on. In this case, the action is to simply print an error message stating that the GPU has already started.
void isGPUOn() {
if (ison) {
ison1++;
} else {
System.err.println("The GPU has " + "been already On!");
}
}
The following program, IfElseDemo, assigns a grade based on the value of a test score: an A for a score of 90% or above, a B for a score of 80% or above, and so on.
class IfElseDemo {
public static void main(String[] args) {
int testscore = 76;
char grade;
if (testscore >= 90) {
grade = 'A';
} else if (testscore >= 80) {
grade = 'B';
} else if (testscore >= 70) {
grade = 'C';
} else if (testscore >= 60) {
grade = 'D';
} else {
grade = 'F';
}
System.out.println("Grade = " + grade);
}
}
The output from the program is:
Grade = C
You may have noticed that the value of testscore can satisfy more than one expression in the compound statement: 76 >= 70 and 76 >= 60. However, once a condition is satisfied, the appropriate statements are executed (grade = 'C' and the remaining conditions are not evaluated.
-------------------------------------- Switches --------------------------------------
Unlike if-then and if-then-else statements, the switch statement can have a number of possible execution paths. A switch works with the byte, short, char, and int primitive data types. It also works with enumerated types, the String class, and a few special classes that wrap certain primitive types: Character, Byte, Short, and Integer.
The following code example, SwitchDemo, declares an int named month whose value represents a month. The code displays the name of the month, based on the value of month, using the switch statement.
public class SwitchDemo {
public static void main(String[] args) {
int month = 8;
String monthString;
switch (month) {
case 1: monthString = "January";
break;
case 2: monthString = "February";
break;
case 3: monthString = "March";
break;
case 4: monthString = "April";
break;
case 5: monthString = "May";
break;
case 6: monthString = "June";
break;
case 7: monthString = "July";
break;
case 8: monthString = "August";
break;
case 9: monthString = "September";
break;
case 10: monthString = "October";
break;
case 11: monthString = "November";
break;
case 12: monthString = "December";
break;
default: monthString = "Invalid month";
break;
}
System.out.println(monthString);
}
}
In this case, August is printed.
The body of a switch statement is known as a switch block. A statement in the switch block can be labeled with one or more case or default labels. The switch statement evaluates its expression, then executes all statements that follow the matching case label.
You could also display the name of the month with if-then-else statements:
int month = 8;
if (month == 1) {
System.out.println("January");
} else if (month == 2) {
System.out.println("February");
}
... // and so on
Deciding whether to use if-then-else statements or a switch statement is based on readability and the expression that the statement is testing. An if-then-else statement can test expressions based on ranges of values or conditions, whereas a switch statement tests expressions based only on a single integer, enumerated value, or String object. They both have their uses.
Another point of interest is the break statement. Each break statement terminates the enclosing switch statement. Control flow continues with the first statement following the switch block. The break statements are necessary because without them, statements in switch blocks fall through: All statements after the matching case label are executed in sequence, regardless of the expression of subsequent case labels, until a break statement is encountered. The program SwitchDemoFallThrough shows statements in a switch block that fall through. The program displays the month corresponding to the integer month and the months that follow in the year:
public class SwitchDemoFallThrough {
public static void main(String args[]) {
java.util.ArrayList<String> futureMonths =
new java.util.ArrayList<String>();
int month = 8;
switch (month) {
case 1: futureMonths.add("January");
case 2: futureMonths.add("February");
case 3: futureMonths.add("March");
case 4: futureMonths.add("April");
case 5: futureMonths.add("May");
case 6: futureMonths.add("June");
case 7: futureMonths.add("July");
case 8: futureMonths.add("August");
case 9: futureMonths.add("September");
case 10: futureMonths.add("October");
case 11: futureMonths.add("November");
case 12: futureMonths.add("December");
break;
default: break;
}
if (futureMonths.isEmpty()) {
System.out.println("Invalid month number");
} else {
for (String monthName : futureMonths) {
System.out.println(monthName);
}
}
}
}
This is the output from the code:
August
September
October
November
December
Technically, the final break is not required because flow falls out of the switch statement. Using a break is recommended so that modifying the code is easier and less error prone. The default section handles all values that are not explicitly handled by one of the case sections.
The following code example, SwitchDemo2, shows how a statement can have multiple case labels. The code example calculates the number of days in a particular month:
class SwitchDemo2 {
public static void main(String[] args) {
int month = 2;
int year = 2000;
int numDays = 0;
switch (month) {
case 1: case 3: case 5:
case 7: case 8: case 10:
case 12:
numDays = 31;
break;
case 4: case 6:
case 9: case 11:
numDays = 30;
break;
case 2:
if (((year % 4 == 0) &&
!(year % 100 == 0))
|| (year % 400 == 0))
numDays = 29;
else
numDays = 28;
break;
default:
System.out.println("Invalid month.");
break;
}
System.out.println("Number of Days = "
+ numDays);
}
}
This is the output from the code:
Number of Days = 29
In Java SE 7 and later, you can use a String object in the switch statement's expression. The following code example, StringSwitchDemo, displays the number of the month based on the value of the String named month:
public class StringSwitchDemo {
public static int getMonthNumber(String month) {
int monthNumber = 0;
if (month == null) {
return monthNumber;
}
switch (month.toLowerCase()) {
case "january":
monthNumber = 1;
break;
case "february":
monthNumber = 2;
break;
case "march":
monthNumber = 3;
break;
case "april":
monthNumber = 4;
break;
case "may":
monthNumber = 5;
break;
case "june":
monthNumber = 6;
break;
case "july":
monthNumber = 7;
break;
case "august":
monthNumber = 8;
break;
case "september":
monthNumber = 9;
break;
case "october":
monthNumber = 10;
break;
case "november":
monthNumber = 11;
break;
case "december":
monthNumber = 12;
break;
default:
monthNumber = 0;
break;
}
return monthNumber;
}
public static void main(String[] args) {
String month = "August";
int returnedMonthNumber =
StringSwitchDemo.getMonthNumber(month);
if (returnedMonthNumber == 0) {
System.out.println("Invalid month");
} else {
System.out.println(returnedMonthNumber);
}
}
}
The output from this code is 8.
The String in the switch expression is compared with the expressions associated with each case label as if the String.equals method were being used. In order for the StringSwitchDemo example to accept any month regardless of case, month is converted to lowercase (with the toLowerCase method), and all the strings associated with the case labels are in lowercase.
Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine. This is a relatively advanced feature and should be used only by developers who have a strong grasp of the fundamentals of the language. With that caveat in mind, reflection is a powerful technique and can enable applications to perform operations which would otherwise be impossible.
Extensibility Features:
An application may make use of external, user-defined classes by creating instances of extensibility objects using their fully-qualified names.
A class browser needs to be able to enumerate the members of classes. Visual development environments can benefit from making use of type information available in reflection to aid the developer in writing correct code.
Debuggers need to be able to examine private members on classes. Test harnesses can make use of reflection to systematically call a discoverable set APIs defined on a class, to insure a high level of code coverage in a test suite.
Drawbacks of Reflection:
Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. The following concerns should be kept in mind when accessing code via reflection. Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.
Reflection requires a runtime permission which may not be present when running under a security manager. This is in an important consideration for code which has to run in a restricted security context, such as in an Applet. Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform.
Since methods of a class either consists of arguments or do not have any argument. So in case of no-argument method noting to worry just simply get class of that object (as we have taken "String" in our example) and after getting class , get that particular method and to invoke this method we have to use invoke() method.
Here is the example code of CallingMethod :
import java.lang.reflect.*;
public class CallingMethod {
public static void main(String[] args) {
String firstName= new String("Deepak");
String lastName=new String("Kumar");
String result = new String("");
Class cls = String.class;
Class[] parametertype = new Class[] {String.class};
Object[] arguments = new Object[] {lastName};
try {
Method concatMethod =
cls.getMethod("concat", parametertype);
result = (String)
concatMethod.invoke(firstName,arguments);
System.out.println(" Concatenated String is =>
"+result);
}catch (Exception e) {
System.out.println(e);
}
}
}
Annotations provide data about a program that is not part of the program itself. They have no direct effect on the operation of the code they annotate.
Annotations have a number of uses, among them:
Information for the compiler — Annotations can be used by the compiler to detect errors or suppress warnings.
Compiler-time and deployment-time processing — Software tools can process annotation information to generate code, XML files, and so forth.
Runtime processing — Some annotations are available to be examined at runtime.
Annotations can be applied to a program's declarations of classes, fields, methods, and other program elements.
The annotation appears first, often (by convention) on its own line, and may include elements with named or unnamed values:
@Author(
name = "Erik Melton",
date = "1/2/2013"
)
class MyClass() { }
Also, if an annotation has no elements, the parentheses may be omitted, as in:
@Override
void mySuperMethod() { }
Many annotations replace what would otherwise have been comments in code.
For example:
public class LMFAO extends LMAO {
// Author: Erik Melton
// Date: 1/2/2013
// Current revision: 6
// Last modified: 1/3/2013
// By: Erik Melton
// Reviewers: Citricsquid, Lord_Ralex, Jbond98
// class code goes here
}
To add this same metadata with an annotation, you must first define the annotation type. The syntax for doing this is:
@interface ClassPreamble {
String author();
String date();
int currentRevision() default 1;
String lastModified() default "N/A";
String lastModifiedBy() default "N/A";
// Note use of array
String[] reviewers();
}
The annotation type definition looks somewhat like an interface definition where the keyword interface is preceded by the @ character (@ = "AT" as in Annotation Type). Annotation types are, in fact, a form of interface, which will be covered in a later lesson. For the moment, you do not need to understand interfaces.
The body of the annotation definition above contains annotation type element declarations, which look a lot like methods. Note that they may define optional default values.
Once the annotation type has been defined, you can use annotations of that type, with the values filled in, like this:
@ClassPreamble (
author = "John Doe",
date = "3/17/2002",
currentRevision = 6,
lastModified = "4/12/2004",
lastModifiedBy = "Jane Doe",
// Note array notation
reviewers = {"Alice", "Bob", "Cindy"}
)
public class LMFAO extends LMAO {
// class code goes here
}
Note: To make the information in @ClassPreamble appear in Javadoc-generated documentation, you must annotate the @ClassPreamble definition itself with the @Documented annotation:
// import this to use @Documented
import java.lang.annotation.*;
@Documented
@interface ClassPreamble {
// Annotation element definitions
}
There are three annotation types that are predefined by the language specification itself: @Deprecated, @Override, and @SuppressWarnings.
@Deprecated:
The @Deprecated annotation indicates that the marked element is deprecated and should no longer be used. The compiler generates a warning whenever a program uses a method, class, or field with the @Deprecated annotation. When an element is deprecated, it should also be documented using the Javadoc @deprecated tag, as shown in the following example. The use of the "@" symbol in both Javadoc comments and in annotations is not coincidental — they are related conceptually. Also, note that the Javadoc tag starts with a lowercase "d" and the annotation starts with an uppercase "D".
// Javadoc comment follows
/**
* @deprecated
* explanation of why it
* was deprecated
*/
@Deprecated
static void deprecatedMethod() { }
}
@Override
The @Override annotation informs the compiler that the element is meant to override an element declared in a superclass (overriding methods will be discussed in the the lesson titled "Interfaces and Inheritance").
// mark method as a superclass method
// that has been overridden
@Override
int overriddenMethod() { }
While it's not required to use this annotation when overriding a method, it helps to prevent errors. If a method marked with @Override fails to correctly override a method in one of its superclasses, the compiler generates an error.
@SuppressWarnings
The @SuppressWarnings annotation tells the compiler to suppress specific warnings that it would otherwise generate. In the example below, a deprecated method is used and the compiler would normally generate a warning. In this case, however, the annotation causes the warning to be suppressed.
// use a deprecated method and tell
// compiler not to generate a warning
@SuppressWarnings("deprecation")
void useDeprecatedMethod() {
// deprecation warning
// - suppressed
objectOne.deprecatedMethod();
}
Every compiler warning belongs to a category. The Java Language Specification lists two categories: "deprecation" and "unchecked." The "unchecked" warning can occur when interfacing with legacy code written before the advent of generics (discussed in the lesson titled "Generics"). To suppress more than one category of warnings, use the following syntax:
@SuppressWarnings({"unchecked", "deprecation"})
The more advanced uses of annotations include writing an annotation processor that can read a Java program and take actions based on its annotations. It might, for example, generate auxiliary source code, relieving the programmer of having to create boilerplate code that always follows predictable patterns. To facilitate this task, release 5.0 of the JDK includes an annotation processing tool, called apt. In release 6 of the JDK, the functionality of apt is a standard part of the Java compiler. Useful if you know how to use it.
To make annotation information available at runtime, the annotation type itself must be annotated with @Retention(RetentionPolicy.RUNTIME), as follows:
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@interface AnnotationForRuntime {
// Elements that give information
// for runtime processing
}
I was just thinking of writing a tutorial teaching people Java basics before trying to get them modding since everyone seems to be trying to just copy+paste with no idea of what they're actually doing. Looks like you beat me to it.
I was just thinking of writing a tutorial teaching people Java basics before trying to get them modding since everyone seems to be trying to just copy+paste with no idea of what they're actually doing. Looks like you beat me to it.
That was my primary reasoning behind this. Thanks. xD
1) Fix the spacing in your code examples, just to follow the usual coding format.
2) Drop the spoilers and use a Table of Contents with anchors instead, and use an overall better layout. The spoiler in spoiler in spoiler in spoiler gets ugly to look at and makes it a pain to read.
3) When you use the code bits, try to always use the [code] tags so that at least they show it is code, instead of the text.
4) When changing topics/parts, try to at least show it. When defining things, like char and int, bold the name so that it is not as shadowed. Bit hard to read tbh.
5) I would move the classes, methods, and packages down below the data types and variables and such, just because really that is how it should be taught.
Overall, cannot wait to see it finished. If you want me to show you examples of probably a way to format it, just ask. (goes for help too)
1) Fix the spacing in your code examples, just to follow the usual coding format.
2) Drop the spoilers and use a Table of Contents with anchors instead, and use an overall better layout. The spoiler in spoiler in spoiler in spoiler gets ugly to look at and makes it a pain to read.
3) When you use the code bits, try to always use the [code] tags so that at least they show it is code, instead of the text.
4) When changing topics/parts, try to at least show it. When defining things, like char and int, bold the name so that it is not as shadowed. Bit hard to read tbh.
5) I would move the classes, methods, and packages down below the data types and variables and such, just because really that is how it should be taught.
Overall, cannot wait to see it finished. If you want me to show you examples of probably a way to format it, just ask. (goes for help too)
I was just getting down the tutorials, in no particular order. I haven't bothered with the formatting yet, I know it needs improving. Any suggestions?
do you know how to change the coding of mod that you didnt make because i would like the mod to be compadable with my mod (but i will give them credit) but when i decmpile it it shows me these useless data types like this (public class ModelTallMan extends awt
{
axx Leg_2;
axx Leg_1;
axx Body;
axx Arm_1;
axx Arm_2;
axx Neck;
axx Head;
axx Arrow_1;
public ModelTallMan()
{
this.t = 64;
this.u = 128;
do you know how to change the coding of mod that you didnt make because i would like the mod to be compadable with my mod (but i will give them credit) but when i decmpile it it shows me these useless data types like this (public class ModelTallMan extends awt
{
axx Leg_2;
axx Leg_1;
axx Body;
axx Arm_1;
axx Arm_2;
axx Neck;
axx Head;
axx Arrow_1;
public ModelTallMan()
{
this.t = 64;
this.u = 128;
public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5)
{
this.Leg_1.f = (ke.b(f * 0.6662F) * 1.4F * f1);
this.Leg_2.f = (ke.b(f * 0.6662F + 3.141593F) * 1.4F * f1);
this.Arm_1.f = (ke.b(f * 0.6662F) * 1.4F * f1);
this.Arm_2.f = (ke.b(f * 0.6662F + 3.141593F) * 1.4F * f1);
}
}
) so do you know how to change it ?
This isn't for minecraft coding, it's for general Java. Also, the reason why it doesn't make sense is because it's obfuscated. You can't just decompile and unobfuscate a mod, it doesn't usually work like that. If you'd like your question answered, post it in JBond98's modding tutorials.
Though this is a minecraft version of http://docs.oracle.com/javase/tutorial/java/TOC.html, it's good to have this thread on the forums with everyone not knowing what to do lol. With Forge being popular, you should go over annotations.
Rollback Post to RevisionRollBack
Same ****, different day - Modification Development Section
Before you mod, you should have at least a basic understanding of how Java works, and the basic syntax of methods and classes. This will be a large expansion of text-based Java tutorials that will help prepare you for venturing into the world of modding. This will help with jbond98's modding tutorials.
This will be in multiple parts, ranging from the basics to advanced topics.
ALL of these tutorials will be done under Java 6, although they should all work correctly if you have Java 7 installed on your computer. I will not be teaching you how to set up your IDE and download the correct JDK, you should have those as prerequisites already. Most of these are from Oracle's tutorials, but I moved some here for easy access.
Each category, (Basic, Beginner, Intermediate, Advanced, User Requests), will be separated. Also, note that the Basic tutorials will be mostly reading and conceptual ideas that are central in Java.
Thanks to Lord_Ralex to helping me format this.
Table of Contents:
Basic Tutorials
Intermediate Tutorials
Advanced Tutorials
--------------------------------------
Data Types:
--------------------------------------
The Java programming language is statically-typed, which means that all variables must first be declared before they can be used. This involves stating the variable's type and name, as you've already seen:
Doing so tells your program that a field named "cpus" exists, holds numerical data, and has an initial value of "1". A variable's data type determines the values it may contain, plus the operations that may be performed on it. In addition to int, the Java programming language supports seven other primitive data types. A primitive type is predefined by the language and is named by a reserved keyword. Primitive values do not share state with other primitive values. The eight primitive data types supported by the Java programming language are:
boolean
The boolean data type has only two possible values: true and false. Use this data type for simple flags that track true/false conditions. This data type represents one bit of information, but its "size" isn't something that's precisely defined.
byte
The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive). The byte data type can be useful for saving memory in large arrays, where the memory savings actually matters. They can also be used in place of int where their limits help to clarify your code; the fact that a variable's range is limited can serve as a form of documentation.
short
The short data type is a 16-bit signed two's complement integer. It has a minimum value of -32,768 and a maximum value of 32,767 (inclusive). As with byte, the same guidelines apply: you can use a short to save memory in large arrays, in situations where the memory savings actually matters.
int
The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive). For integral values, this data type is generally the default choice unless there is a reason (like the above) to choose something else. This data type will most likely be large enough for the numbers your program will use, but if you need a wider range of values, use long instead.
long
The long data type is a 64-bit signed two's complement integer. It has a minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807 (inclusive). Use this data type when you need a range of values wider than those provided by int.
float
The float data type is a single-precision 32-bit IEEE 754 floating point. Its range of values is beyond the scope of this discussion, but is specified in the Floating-Point Types, Formats, and Values section of the Java Language Specification. As with the recommendations for byte and short, use a float (instead of double) if you need to save memory in large arrays of floating point numbers. This data type should never be used for precise values, such as currency. For that, you will need to use the java.math.BigDecimal class instead. Numbers and Strings covers BigDecimal and other useful classes provided by the Java platform.
double
The double data type is a double-precision 64-bit IEEE 754 floating point. Its range of values is beyond the scope of this discussion, but is specified in the Floating-Point Types, Formats, and Values section of the Java Language Specification. For decimal values, this data type is generally the default choice. As mentioned above, this data type should never be used for precise values, such as currency.
char
The char data type is a single 16-bit Unicode character. It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive).
String
In addition to the eight primitive data types listed above, the Java programming language also provides special support for character strings via the java.lang.String class. Enclosing your character string within double quotes will automatically create a new String object; for example, String s = "this is a string";. String objects are immutable, which means that once created, their values cannot be changed. The String class is not technically a primitive data type, but considering the special support given to it by the language, you'll probably tend to think of it as such. You'll learn more about the String class in Simple Data Objects
--------------------------------------
Variables:
--------------------------------------
An object stores its state in fields.
In the Java programming language, the terms "field" and "variable" are both used; this is a common source of confusion among new developers, since both often seem to refer to the same thing.
The Java programming language defines the following kinds of variables:
Local
Similar to how an object stores its state in fields, a method will often store its temporary state in local variables. The syntax for declaring a local variable is similar to declaring a field (for example, int count = 0;). There is no special keyword designating a variable as local; that determination comes entirely from the location in which the variable is declared — which is between the opening and closing braces of a method. As such, local variables are only visible to the methods in which they are declared; they are not accessible from the rest of the class.
Instance
Technically speaking, objects store their individual states in "non-static fields", that is, fields declared without the static keyword. Non-static fields are also known as instance variables because their values are unique to each instance of a class (to each object, in other words); the currentSpeed of one computer is independent from the currentSpeed of another.
Class
A class variable is any field declared with the static modifier; this tells the compiler that there is exactly one copy of this variable in existence, regardless of how many times the class has been instantiated. A field defining the number of CPUs for a particular kind of computer could be marked as static since conceptually the same number of CPUs will apply to all instances. The code static int numCPUs = 6; would create such a static field. Additionally, the keyword final could be added to indicate that the number of CPUs will never change.
Parameter
You've already seen examples of parameters, in the Computer class. Recall that the signature for the main method is public static void main(String[] args). Here, the args variable is the parameter to this method. The important thing to remember is that parameters are always classified as "variables" not "fields". This applies to other parameter-accepting constructs as well (such as constructors and exception handlers) that you'll learn about later in the tutorial.
Having said that, the remainder of this tutorial uses the following general guidelines when discussing fields and variables. If we are talking about "fields in general" (excluding local variables and parameters), we may simply say "fields". If the discussion applies to "all of the above", we may simply say "variables". If the context calls for a distinction, we will use specific terms (static field, local variables, etc.) as appropriate. You may also occasionally see the term "member" used as well. A type's fields, methods, and nested types are collectively called its members.
--------------------------------------
Naming:
--------------------------------------
Every programming language has its own set of rules and conventions for the kinds of names that you're allowed to use, and the Java programming language is no different. The rules and conventions for naming your variables can be summarized as follows:
Variable names are case-sensitive. A variable's name can be any legal identifier — an unlimited-length sequence of Unicode letters and digits, beginning with a letter, the dollar sign "$", or the underscore character "_". The convention, however, is to always begin your variable names with a letter, not "$" or "_". Additionally, the dollar sign character, by convention, is never used at all. You may find some situations where auto-generated names will contain the dollar sign, but your variable names should always avoid using it. A similar convention exists for the underscore character; while it's technically legal to begin your variable's name with "_", this practice is discouraged. White space is not permitted.
Subsequent characters may be letters, digits, dollar signs, or underscore characters. Conventions (and common sense) apply to this rule as well. When choosing a name for your variables, use full words instead of cryptic abbreviations. Doing so will make your code easier to read and understand. In many cases it will also make your code self-documenting; fields named cadence, speed, and gear, for example, are much more intuitive than abbreviated versions, such as s, c, and g. Also keep in mind that the name you choose must not be a keyword or reserved word.
If the name you choose consists of only one word, spell that word in all lowercase letters. If it consists of more than one word, capitalize the first letter of each subsequent word. The names cpuRatio and currentCPU are prime examples of this convention. If your variable stores a constant value, such as static final int NUM_CPUS = 6, the convention changes slightly, capitalizing every letter and separating subsequent words with the underscore character. By convention, the underscore character is never used elsewhere.
--------------------------------------
Default Values:
--------------------------------------
It's not always necessary to assign a value when a field is declared. Fields that are declared but not initialized will be set to a reasonable default by the compiler. Generally speaking, this default will be zero or null, depending on the data type. Relying on such default values, however, is generally considered bad programming style.
The following chart summarizes the default values for the above data types.
Data Type | Default Value (for fields)
byte | 0
short |0
int |0
long |0L
float |0.0f
double |0.0d
char |'\u0000'
String (or any object) | null
boolean | false
Local variables are slightly different; the compiler never assigns a default value to an uninitialized local variable. If you cannot initialize your local variable where it is declared, make sure to assign it a value before you attempt to use it. Accessing an uninitialized local variable will result in a compile-time error.
--------------------------------------
Classes:
--------------------------------------
In real life, you'll find many instances of a specific object. For example, computers. All computers do the fundamentally same thing, but they have different specific parts. Each computer is built from blueprints, and then slightly modified to fit the user's needs. In object-oriented terms, we say that your computer is an instance of the class of objects known as computers. A class is the blueprint from which individual objects are created.
For example, look at the following. (You do not need to be able to understand it, just read it)
The syntax will look alien, but it's really not that bad. The fields numOfScreens, numOfGPUs, and clockSpeed represent the Object's state, and the methods checkSums and clockGPUs define it's interactions with other classes and objects. This code, on it's own, does not run, as it does not contain the main() method. This is just a blueprint for each computer you want to run. It's the responsibility of creating and using new Computer objects belongs to some different class in your application.
Here's an example that WILL run:
This code, combined with the example above, will run. Look in the console to see what it prints.
--------------------------------------
Objects:
--------------------------------------
Objects are the fundemental basics of Java. Java is an object oreinted language, and deals with objects. Objects have state and behavior. The State of an object are all of the variables and their values that are set within the object's class. It's behavior are the methods you program into it to allow it to function in your program or mod.
For example, say you have a Dog object. It has multiple states. Breed, gender, height, width are all states of the Dog object, for example. The dog object also has a few behaviors, or methods. It can bark(), run(), chaseCat() and eat(). The states (variables) all affect what the object can, or cannot do.
Objects have 4 main benefits:
--------------------------------------
Inheritance:
--------------------------------------
Different kinds of objects often have things in common with others. Gaming computers, general computers, and work computer all are computers, but have slightly different things about them. Gaming computers are high quality, regular computers are regular, and work computers are ergonomic. Object oriented programming allows classes and objects to inherit other objects properties. There would be a Superclass Computer, with the subclasses of gaming, regular, and work computers, as they have specific functions.
The syntax for doing this is simple.
This gives GamingComputer all of the same fields and methods as Computer, but allows the class to only focus on exactly what makes it different. This makes the code very easy and simple to read. You must take care to make sure that you document your files, otherwise it will be horrendously confusing to the programmers that you work with. The superclass code will not appear in the subclass directly, but will be useable.
--------------------------------------
Packages:
--------------------------------------
Packages are quite simple. Think of them as a folder. You have a folder for the GUI code, a folder for the sound code, and a folder for the network code. Each of those "folders" are packages. They allow the coders to be able to quickly identify different parts of the code.
--------------------------------------
Literals:
--------------------------------------
You may have noticed that the new keyword isn't used when initializing a variable of a primitive type. Primitive types are special data types built into the language; they are not objects created from a class. A literal is the source code representation of a fixed value; literals are represented directly in your code without requiring computation. As shown below, it's possible to assign a literal to a variable of a primitive type:
Integer Literals:
An integer literal is of type long if it ends with the letter L or l; otherwise it is of type int. It is recommended that you use the upper case letter L because the lower case letter l is hard to distinguish from the digit 1.
Values of the integral types byte, short, int, and long can be created from int literals. Values of type long that exceed the range of int can be created from long literals. Integer literals can be expressed by these number systems:
Decimal: Base 10, whose digits consists of the numbers 0 through 9; this is the number system you use every day
Hexadecimal: Base 16, whose digits consist of the numbers 0 through 9 and the letters A through F
Binary: Base 2, whose digits consists of the numbers 0 and 1 (you can create binary literals in Java SE 7 and later)
For general-purpose programming, the decimal system is likely to be the only number system you'll ever use. However, if you need to use another number system, the following example shows the correct syntax. The prefix 0x indicates hexadecimal and 0b indicates binary:
Floating-Point Literals:
A floating-point literal is of type float if it ends with the letter F or f; otherwise its type is double and it can optionally end with the letter D or d.
The floating point types (float and double) can also be expressed using E or e (for scientific notation), F or f (32-bit float literal) and D or d (64-bit double literal; this is the default and by convention is omitted).
Character and String Literals:
Literals of types char and String may contain any Unicode (UTF-16) characters. If your editor and file system allow it, you can use such characters directly in your code. If not, you can use a "Unicode escape" such as '\u0108' (capital C with circumflex), or "S\u00ED Se\u00F1or" (Sí Señor in Spanish). Always use 'single quotes' for char literals and "double quotes" for String literals. Unicode escape sequences may be used elsewhere in a program (such as in field names, for example), not just in char or String literals.
The Java programming language also supports a few special escape sequences for char and String literals: \b (backspace), \t (tab), \n (line feed), \f (form feed), \r (carriage return), \" (double quote), \' (single quote), and \\ (backslash).
There's also a special null literal that can be used as a value for any reference type. null may be assigned to any variable, except variables of primitive types. There's little you can do with a null value beyond testing for its presence. Therefore, null is often used in programs as a marker to indicate that some object is unavailable.
Class Literal:
Finally, there's also a special kind of literal called a class literal, formed by taking a type name and appending ".class"; for example, String.class. This refers to the object (of type Class) that represents the type itself.
Using Underscore Characters in Numeric Literals:
In Java SE 7 and later, any number of underscore characters (_) can appear anywhere between digits in a numerical literal. This feature enables you, for example. to separate groups of digits in numeric literals, which can improve the readability of your code.
For instance, if your code contains numbers with many digits, you can use an underscore character to separate digits in groups of three, similar to how you would use a punctuation mark like a comma, or a space, as a separator.
The following example shows other ways you can use the underscore in numeric literals:
You can place underscores only between digits; you cannot place underscores in the following places:
--------------------------------------
Arrays:
--------------------------------------
An array is a container object that holds a fixed number of values of a single type. The length of an array is established when the array is created. After creation, its length is fixed.
Each item in an array is called an element, and each element is accessed by its numerical index. As shown in the above illustration, numbering begins with 0. The 9th element, for example, would therefore be accessed at index 8.
The following program, ArrayDemo, creates an array of integers, puts some values in it, and prints each value to standard output.
The output from this program is:
In a real-world programming situation, you'd probably use one of the supported looping constructs to iterate through each element of the array, rather than write each line individually as shown above. However, this example clearly illustrates the array syntax.
The above program declares anArray with the following line of code:
Like declarations for variables of other types, an array declaration has two components: the array's type and the array's name. An array's type is written as type[], where type is the data type of the contained elements; the square brackets are special symbols indicating that this variable holds an array. The size of the array is not part of its type (which is why the brackets are empty). An array's name can be anything you want, provided that it follows the rules and conventions as previously discussed in the naming section. As with variables of other types, the declaration does not actually create an array — it simply tells the compiler that this variable will hold an array of the specified type.
Similarly, you can declare arrays of other types:
You can also place the square brackets after the array's name:
However, convention discourages this form; the brackets identify the array type and should appear with the type designation.
One way to create an array is with the new operator. The next statement in the ArrayDemo program allocates an array with enough memory for ten integer elements and assigns the array to the anArray variable.
If this statement were missing, the compiler would print an error like the following, and compilation would fail:
The next few lines assign values to each element of the array:
Each array element is accessed by its numerical index:
Alternatively, you can use the shortcut syntax to create and initialize an array:
Here the length of the array is determined by the number of values provided between { and }.
You can also declare an array of arrays (also known as a multidimensional array) by using two or more sets of square brackets, such as String[][] names. Each element, therefore, must be accessed by a corresponding number of index values.
In the Java programming language, a multidimensional array is simply an array whose components are themselves arrays. This is unlike arrays in C or Fortran. A consequence of this is that the rows are allowed to vary in length, as shown in the following MultiDimArrayDemoprogram:
The output from this program is:
Finally, you can use the built-in length property to determine the size of any array. The code
will print the array's size to standard output.
The System class has an arraycopy method that you can use to efficiently copy data from one array into another:
The two Object arguments specify the array to copy from and the array to copy to. The three int arguments specify the starting position in the source array, the starting position in the destination array, and the number of array elements to copy.
The following program, ArrayCopyDemo, declares an array of char elements, spelling the word "decaffeinated". It uses arraycopy to copy a subsequence of array components into a second array:
The output from this program is:
--------------------------------------
Expressions, Statements, and Blocks:
--------------------------------------
It's time to learn about expressions, statements, and blocks. Operators may be used in building expressions, which compute values; expressions are the core components of statements; statements may be grouped into blocks.
An expression is a construct made up of variables, operators, and method invocations, which are constructed according to the syntax of the language, that evaluates to a single value.
The data type of the value returned by an expression depends on the elements used in the expression. The expression cadence = 0 returns an int because the assignment operator returns a value of the same data type as its left-hand operand; in this case, cadence is an int. As you can see from the other expressions, an expression can return other types of values as well, such as boolean or String.
The Java programming language allows you to construct compound expressions from various smaller expressions as long as the data type required by one part of the expression matches the data type of the other. Here's an example of a compound expression:
In this particular example, the order in which the expression is evaluated is unimportant because the result of multiplication is independent of order; the outcome is always the same, no matter in which order you apply the multiplications. However, this is not true of all expressions. For example, the following expression gives different results, depending on whether you perform the addition or the division operation first:
You can specify exactly how an expression will be evaluated using balanced parenthesis: ( and ). For example, to make the previous expression unambiguous, you could write the following:
If you don't explicitly indicate the order for the operations to be performed, the order is determined by the precedence assigned to the operators in use within the expression. Operators that have a higher precedence get evaluated first. For example, the division operator has a higher precedence than does the addition operator. Therefore, the following two statements are equivalent:
When writing compound expressions, be explicit and indicate with parentheses which operators should be evaluated first. This practice makes code easier to read and to maintain.
Statements are roughly equivalent to sentences in natural languages. A statement forms a complete unit of execution. The following types of expressions can be made into a statement by terminating the expression with a semicolon ( .
In addition to expression statements, there are two other kinds of statements: declaration statements and control flow statements. A declaration statement declares a variable. You've seen many examples of declaration statements already:
Finally, control flow statements regulate the order in which statements get executed.
A block is a group of zero or more statements between balanced braces and can be used anywhere a single statement is allowed. The following example, BlockDemo, illustrates the use of blocks:
--------------------------------------
If and Else:
--------------------------------------
The if-then statement is the most basic of all the control flow statements. It tells your program to execute a certain section of code only if a particular test evaluates to true. One possible implementation of the turnonGPU method could be as follows:
If this test evaluates to false (meaning that the GPU not running), control jumps to the end of the if-then statement.
In addition, the opening and closing braces are optional, provided that the "then" clause contains only one statement:
Deciding when to omit the braces is a matter of personal taste. Omitting them can make the code more brittle. If a second statement is later added to the "then" clause, a common mistake would be forgetting to add the newly required braces. The compiler cannot catch this sort of error; you'll just get the wrong results.
The if-then-else statement provides a secondary path of execution when an "if" clause evaluates to false. You could use an if-then-else statement in the isGPUOn method to take some action if the whatevers are applied when the GPU is not on. In this case, the action is to simply print an error message stating that the GPU has already started.
The following program, IfElseDemo, assigns a grade based on the value of a test score: an A for a score of 90% or above, a B for a score of 80% or above, and so on.
The output from the program is:
Grade = C
You may have noticed that the value of testscore can satisfy more than one expression in the compound statement: 76 >= 70 and 76 >= 60. However, once a condition is satisfied, the appropriate statements are executed (grade = 'C' and the remaining conditions are not evaluated.
--------------------------------------
Switches
--------------------------------------
Unlike if-then and if-then-else statements, the switch statement can have a number of possible execution paths. A switch works with the byte, short, char, and int primitive data types. It also works with enumerated types, the String class, and a few special classes that wrap certain primitive types: Character, Byte, Short, and Integer.
The following code example, SwitchDemo, declares an int named month whose value represents a month. The code displays the name of the month, based on the value of month, using the switch statement.
In this case, August is printed.
The body of a switch statement is known as a switch block. A statement in the switch block can be labeled with one or more case or default labels. The switch statement evaluates its expression, then executes all statements that follow the matching case label.
You could also display the name of the month with if-then-else statements:
Deciding whether to use if-then-else statements or a switch statement is based on readability and the expression that the statement is testing. An if-then-else statement can test expressions based on ranges of values or conditions, whereas a switch statement tests expressions based only on a single integer, enumerated value, or String object. They both have their uses.
Another point of interest is the break statement. Each break statement terminates the enclosing switch statement. Control flow continues with the first statement following the switch block. The break statements are necessary because without them, statements in switch blocks fall through: All statements after the matching case label are executed in sequence, regardless of the expression of subsequent case labels, until a break statement is encountered. The program SwitchDemoFallThrough shows statements in a switch block that fall through. The program displays the month corresponding to the integer month and the months that follow in the year:
This is the output from the code:
Technically, the final break is not required because flow falls out of the switch statement. Using a break is recommended so that modifying the code is easier and less error prone. The default section handles all values that are not explicitly handled by one of the case sections.
The following code example, SwitchDemo2, shows how a statement can have multiple case labels. The code example calculates the number of days in a particular month:
This is the output from the code:
In Java SE 7 and later, you can use a String object in the switch statement's expression. The following code example, StringSwitchDemo, displays the number of the month based on the value of the String named month:
The output from this code is 8.
The String in the switch expression is compared with the expressions associated with each case label as if the String.equals method were being used. In order for the StringSwitchDemo example to accept any month regardless of case, month is converted to lowercase (with the toLowerCase method), and all the strings associated with the case labels are in lowercase.
---------------------------------------
Coming Soon!
---------------------------------------
--------------------------------------
Reflection:
--------------------------------------
Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine. This is a relatively advanced feature and should be used only by developers who have a strong grasp of the fundamentals of the language. With that caveat in mind, reflection is a powerful technique and can enable applications to perform operations which would otherwise be impossible.
Extensibility Features:
An application may make use of external, user-defined classes by creating instances of extensibility objects using their fully-qualified names.
A class browser needs to be able to enumerate the members of classes. Visual development environments can benefit from making use of type information available in reflection to aid the developer in writing correct code.
Debuggers need to be able to examine private members on classes. Test harnesses can make use of reflection to systematically call a discoverable set APIs defined on a class, to insure a high level of code coverage in a test suite.
Drawbacks of Reflection:
Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. The following concerns should be kept in mind when accessing code via reflection. Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.
Reflection requires a runtime permission which may not be present when running under a security manager. This is in an important consideration for code which has to run in a restricted security context, such as in an Applet. Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform.
Since methods of a class either consists of arguments or do not have any argument. So in case of no-argument method noting to worry just simply get class of that object (as we have taken "String" in our example) and after getting class , get that particular method and to invoke this method we have to use invoke() method.
Here is the example code of CallingMethod :
--------------------------------------
Annotations! (@):
--------------------------------------
Annotations provide data about a program that is not part of the program itself. They have no direct effect on the operation of the code they annotate.
Annotations have a number of uses, among them:
or
If there is just one element named "value," then the name may be omitted, as in:
Also, if an annotation has no elements, the parentheses may be omitted, as in:
Many annotations replace what would otherwise have been comments in code.
For example:
To add this same metadata with an annotation, you must first define the annotation type. The syntax for doing this is:
The annotation type definition looks somewhat like an interface definition where the keyword interface is preceded by the @ character (@ = "AT" as in Annotation Type). Annotation types are, in fact, a form of interface, which will be covered in a later lesson. For the moment, you do not need to understand interfaces.
The body of the annotation definition above contains annotation type element declarations, which look a lot like methods. Note that they may define optional default values.
Once the annotation type has been defined, you can use annotations of that type, with the values filled in, like this:
Note: To make the information in @ClassPreamble appear in Javadoc-generated documentation, you must annotate the @ClassPreamble definition itself with the @Documented annotation:
There are three annotation types that are predefined by the language specification itself: @Deprecated, @Override, and @SuppressWarnings.
@Deprecated:
The @Deprecated annotation indicates that the marked element is deprecated and should no longer be used. The compiler generates a warning whenever a program uses a method, class, or field with the @Deprecated annotation. When an element is deprecated, it should also be documented using the Javadoc @deprecated tag, as shown in the following example. The use of the "@" symbol in both Javadoc comments and in annotations is not coincidental — they are related conceptually. Also, note that the Javadoc tag starts with a lowercase "d" and the annotation starts with an uppercase "D".
@Override
The @Override annotation informs the compiler that the element is meant to override an element declared in a superclass (overriding methods will be discussed in the the lesson titled "Interfaces and Inheritance").
While it's not required to use this annotation when overriding a method, it helps to prevent errors. If a method marked with @Override fails to correctly override a method in one of its superclasses, the compiler generates an error.
@SuppressWarnings
The @SuppressWarnings annotation tells the compiler to suppress specific warnings that it would otherwise generate. In the example below, a deprecated method is used and the compiler would normally generate a warning. In this case, however, the annotation causes the warning to be suppressed.
Every compiler warning belongs to a category. The Java Language Specification lists two categories: "deprecation" and "unchecked." The "unchecked" warning can occur when interfacing with legacy code written before the advent of generics (discussed in the lesson titled "Generics"). To suppress more than one category of warnings, use the following syntax:
The more advanced uses of annotations include writing an annotation processor that can read a Java program and take actions based on its annotations. It might, for example, generate auxiliary source code, relieving the programmer of having to create boilerplate code that always follows predictable patterns. To facilitate this task, release 5.0 of the JDK includes an annotation processing tool, called apt. In release 6 of the JDK, the functionality of apt is a standard part of the Java compiler. Useful if you know how to use it.
To make annotation information available at runtime, the annotation type itself must be annotated with @Retention(RetentionPolicy.RUNTIME), as follows:
That's all you need to know.
[represent]
That was my primary reasoning behind this. Thanks. xD
Check out my Minecraft Modding Tutorials!
1) Fix the spacing in your code examples, just to follow the usual coding format.
2) Drop the spoilers and use a Table of Contents with anchors instead, and use an overall better layout. The spoiler in spoiler in spoiler in spoiler gets ugly to look at and makes it a pain to read.
3) When you use the code bits, try to always use the [code] tags so that at least they show it is code, instead of the text.
4) When changing topics/parts, try to at least show it. When defining things, like char and int, bold the name so that it is not as shadowed. Bit hard to read tbh.
5) I would move the classes, methods, and packages down below the data types and variables and such, just because really that is how it should be taught.
Overall, cannot wait to see it finished. If you want me to show you examples of probably a way to format it, just ask. (goes for help too)
I was just getting down the tutorials, in no particular order. I haven't bothered with the formatting yet, I know it needs improving. Any suggestions?
Thanks, I'm still working on it, it's highly WIP right now.
Thanks, I'm adding a LOT more, it's just the barebones right now for reading Java code.
Arrays
if else statements
blocks
I'm still adding tutorials on there, any you'd like to see?
Switch Statements
Next up:
While loops
For loops
Find out how I generate....coolAlias...world structure generation and rotation tool...
{
axx Leg_2;
axx Leg_1;
axx Body;
axx Arm_1;
axx Arm_2;
axx Neck;
axx Head;
axx Arrow_1;
public ModelTallMan()
{
this.t = 64;
this.u = 128;
this.Leg_2 = new axx(this, 0, 0);
this.Leg_2.a(-1.0F, 0.0F, -1.0F, 2, 36, 2);
this.Leg_2.a(-2.0F, 0.0F, 1.0F);
this.Leg_2.b(64, 128);
this.Leg_2.i = true;
setRotation(this.Leg_2, 0.0F, 0.0F, 0.0F);
this.Leg_1 = new axx(this, 0, 0);
this.Leg_1.a(-1.0F, 0.0F, -1.0F, 2, 36, 2);
this.Leg_1.a(2.0F, 0.0F, 1.0F);
this.Leg_1.b(64, 128);
this.Leg_1.i = true;
setRotation(this.Leg_1, 0.0F, 0.0F, 0.0F);
this.Body = new axx(this, 15, 23);
this.Body.a(0.0F, 0.0F, 0.0F, 10, 35, 8);
this.Body.a(-5.0F, -35.0F, -3.0F);
this.Body.b(64, 128);
this.Body.i = true;
setRotation(this.Body, 0.0F, 0.0F, 0.0F);
this.Arm_1 = new axx(this, 53, 17);
this.Arm_1.a(-1.0F, 0.0F, -1.0F, 2, 40, 2);
this.Arm_1.a(-6.0F, -35.0F, 0.0F);
this.Arm_1.b(64, 128);
this.Arm_1.i = true;
setRotation(this.Arm_1, 0.0F, 0.0F, 0.0F);
this.Arm_2 = new axx(this, 53, 17);
this.Arm_2.a(-1.0F, 0.0F, -1.0F, 2, 40, 2);
this.Arm_2.a(6.0F, -35.0F, 1.0F);
this.Arm_2.b(64, 128);
this.Arm_2.i = true;
setRotation(this.Arm_2, 0.0F, 0.0F, 0.0F);
this.Neck = new axx(this, 45, 1);
this.Neck.a(0.0F, 0.0F, -0.466667F, 4, 7, 5);
this.Neck.a(-2.0F, -42.0F, -1.0F);
this.Neck.b(64, 128);
this.Neck.i = true;
setRotation(this.Neck, 0.0F, 0.0F, 0.0F);
this.Head = new axx(this, 26, 88);
this.Head.a(0.0F, 0.0F, 0.0F, 8, 8, 8);
this.Head.a(-4.0F, -50.0F, -3.0F);
this.Head.b(64, 128);
this.Head.i = true;
setRotation(this.Head, 0.0F, 0.0F, 0.0F);
this.Arrow_1 = new axx(this, 8, 74);
this.Arrow_1.a(0.0F, 0.0F, 0.0F, 17, 1, 1);
this.Arrow_1.a(-8.0F, -49.0F, 0.0F);
this.Arrow_1.b(64, 128);
this.Arrow_1.i = true;
setRotation(this.Arrow_1, 0.0F, 0.0F, 0.244346F);
}
public void a(lq entity, float f, float f1, float f2, float f3, float f4, float f5)
{
super.a(entity, f, f1, f2, f3, f4, f5);
setRotationAngles(f, f1, f2, f3, f4, f5);
this.Leg_2.a(f5);
this.Leg_1.a(f5);
this.Body.a(f5);
this.Arm_1.a(f5);
this.Arm_2.a(f5);
this.Neck.a(f5);
this.Head.a(f5);
this.Arrow_1.a(f5);
}
private void setRotation(axx model, float x, float y, float z)
{
model.f = x;
model.g = y;
model.h = z;
}
public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5)
{
this.Leg_1.f = (ke.b(f * 0.6662F) * 1.4F * f1);
this.Leg_2.f = (ke.b(f * 0.6662F + 3.141593F) * 1.4F * f1);
this.Arm_1.f = (ke.b(f * 0.6662F) * 1.4F * f1);
this.Arm_2.f = (ke.b(f * 0.6662F + 3.141593F) * 1.4F * f1);
}
}
) so do you know how to change it ?
No problem. I'm going to add more, but haven't had the time. Anything you'd like to see?
This isn't for minecraft coding, it's for general Java. Also, the reason why it doesn't make sense is because it's obfuscated. You can't just decompile and unobfuscate a mod, it doesn't usually work like that. If you'd like your question answered, post it in JBond98's modding tutorials.
Thanks.
I haven't had much time to add anything, but I have some general programming things up.
Any suggestions or requests?