Last active
April 3, 2022 15:56
-
-
Save 0xmycf/b2ea7b9102a3f4b65cf7f130332926e3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package cheatsheet.java; | |
// Imports | |
import java.util.function.Supplier; | |
import java.util.stream.Stream; | |
// This is the basic class of a Java program. | |
public class Main { | |
// Classes can hold values, these values are called fields. | |
// Fields are declared with a type and a name. | |
// Fields can use modifiers: | |
// public: can be accessed from anywhere | |
// private: can only be accessed from within the class | |
// protected: can be accessed from within the class and from subclasses | |
// static: belongs to the class, not to an instance | |
// final: cannot be changed | |
// there are a few more: https://www.w3schools.com/java/java_modifiers.asp | |
private int field1; // uninitialized | |
private final int field2 = 2; // initialized | |
protected final int field3 = 3; // initialized, protected and final | |
// Classes use a constructor to initialize their fields. | |
// Constructors are declared with the same name as the class. | |
// Constructors can have parameters. | |
// Constructors can use modifiers: | |
Main(int field1) { | |
this.field1 = field1; | |
} | |
// Constructers can be overloaden | |
// That means there can be multiple constructors with the same name | |
// but with different parameters. | |
Main(int field1, int field2) { | |
this.field1 = field1; | |
System.out.println("field2 = " + field2); | |
} | |
// This is the main method of a Java program. | |
// Every program needs it to run. | |
// The argument String[] args is the argument list of the program. | |
// eg: $ java Main "Hello" "World" | |
public static void main(String[] args) { | |
// Printing stuff in Java | |
System.out.println("Hello, World!"); | |
// It also works with other types | |
System.out.println(42); | |
System.out.println(true); | |
// Declaring variables in Java | |
// The default pattern is: | |
// TYPE NAME = VALUE; | |
int x; // an uninitialized integer (as primitive) | |
int y = 42; // an initialized integer (as primitive) | |
Integer z; // an uninitialized integer (as object) | |
Integer w = 42; // an initialized integer (as object) | |
// modifiers for variables: | |
// final | |
// (see https://docs.oracle.com/javase/tutorial/java/javaOO/fields.html) | |
// Examples: | |
int a = 1; | |
final int b = 2; | |
// Java also supports the var keyword, which will infer the type | |
// note that var can only be used if a variable type can be inferred | |
// so "var x;" is not allowed | |
var c = 3; | |
// reassigning a final variable is not allowed | |
// a = 3; // error: reassignment of final variable 'a' | |
// creating a new object works with the new keyword | |
// Note that you should not create Integers like that | |
var d = new Integer(4); | |
} | |
// This is a method of a Java program. | |
// The pattern is: | |
// MODIFIERS RETURN-TYPE NAME(TYPE PARAMETER, ...) { | |
// void is a special return type indicating that the method does not return anything | |
// Methods can be overloaden, just like constructors | |
void controlFlow() { | |
// Control flow in Java | |
// if-else | |
if (true) { | |
// do something | |
} else { | |
// do something else | |
} | |
// There is also a special if syntax | |
// ModBlock x = new ModBlock(); | |
// if (x instanceof Block block) { | |
// // no need to cast x to Block | |
// // do something | |
// } | |
// switch (old) | |
switch (42) { | |
case 1: | |
// do something | |
break; | |
case 2: | |
// do something else | |
break; | |
default: | |
// do something else | |
break; | |
} | |
// switch (new) also called enhanced switch | |
switch (42) { | |
case 1 -> System.out.println("1"); | |
case 2 -> System.out.println("2"); | |
default -> System.out.println("default"); | |
} | |
// while | |
while (true) { | |
// do something | |
// break for getting out | |
break; | |
} | |
// do-while | |
do { | |
// do something | |
break; | |
} while (true); | |
// for | |
// int could be var here | |
for (int i = 0; i < 10; i++) { | |
// do something | |
} | |
// for-each | |
for (String s : new String[]{"Hello", "World"}) { | |
// do something | |
} | |
} | |
// Method modifiers: | |
// public - accessible from everywhere | |
// private - accessible only from the class | |
// protected - accessible from the class and subclasses | |
// static - the method is not connected to an object but to the class itself | |
// final - the method cannot be overridden in subclasses | |
// there are a few more | |
// https://www.w3schools.com/java/java_modifiers.asp | |
public int publicMethod() { | |
return 42; | |
} | |
private int privateMethod() { | |
return 42; | |
} | |
protected int protectedMethod() { | |
return 42; | |
} | |
int defaultMethod() { | |
return 42; | |
} | |
final int finalMethod() { | |
return 42; | |
} | |
// This method can be called like that: | |
// Main.publicMethod(); | |
// instead of the others like: | |
// var foo = new Main(); | |
// foo.publicMethod(); | |
static int staticMethod() { | |
return 42; | |
} | |
// static final makes no sense | |
// private final makes no sense | |
// but this is how methods use many modifiers | |
static final private int staticFinalPrivateMethod() { | |
return 42; | |
} | |
// Methods can hold classes too | |
private int methodWithClass() { | |
class InnerClass { | |
// ... | |
} | |
return 42; | |
} | |
// Nested functions are not allowed | |
// void methodWithFunction() { | |
// void innerFunction() { | |
// } | |
// } | |
// Anonymous functions are allowed | |
// but are objects of functional interfaces, such as Runnable, Supplier, etc. | |
void anonymousFunction() { | |
// Sometimes also called lambda expressions | |
Runnable r = () -> { | |
// do something | |
}; | |
var i = 2; | |
// Lambdas can capture their environment | |
// This also uses the ternary operator | |
// an inline if | |
Supplier<String> s = () -> i > 0 ? "Less" : "More"; | |
// The stream API uses lambdas extensively | |
var stream = Stream.of(1, 2, 3); | |
// forEach is a method of the stream | |
// it takes a lambda as a parameter and calls it for each element | |
// Here we use the System.out::println method reference because its shorter and more readable than | |
// (e) -> System.out.println(e); | |
// This is called point-free style | |
stream.forEach(System.out::println); | |
// this is with the full lambda | |
stream.forEach(e -> System.out.println(e)); | |
} | |
} | |
// There can ever be one class per file | |
// for completion purposes, we will have more in here | |
// classes can also be nested | |
// Classes can have the following modifiers: | |
// static (only nested), final, abstract | |
// https://www.w3schools.com/java/java_modifiers.asp | |
class OuterClass { | |
// Nested classes can be static | |
// static classes can be initialized without the outer class | |
class NestedClass { | |
// ... | |
} | |
} | |
// There are other types of classes | |
// interfaces | |
// records | |
// enums | |
// Enums are enumerations | |
enum MyEnum { | |
Low(1), | |
Medium(3), | |
High(5); // semi-colon needed if methods follow | |
private int value; | |
MyEnum(int value) { | |
this.value = value; | |
} | |
// Enums can have methods | |
public int getValue() { | |
return value; | |
} | |
} | |
// Records are similar to classes | |
// They can have fields and methods | |
// Records are immutable | |
// They are basically data-classes | |
record Record(int x, int y) { | |
void someMethod() { | |
// ... | |
} | |
} | |
// Interfaces allow for multiple inheritance | |
interface Interface1 { | |
// Normally methods in interfaces are abstract and have to be implemented by their inheriting classes | |
void doSomething(); | |
} | |
interface Interface2 {} | |
// This is how inheritance works | |
class A { | |
// This is a method | |
void stuff() { | |
// ... | |
} | |
} | |
class B extends A implements Interface1, Interface2 { | |
// Implementing the interface | |
@Override | |
public void doSomething() { | |
} | |
// Overriding the method | |
@Override | |
void stuff() { | |
// ... | |
} | |
} | |
// Java also supports generics | |
class Wrapper<T> { | |
// Fields can now access T | |
T value; | |
// ... | |
// The constructor can now access T | |
Wrapper(T value) { | |
this.value = value; | |
} | |
// Methods can now access T | |
void doSomething(T value) { | |
// ... | |
} | |
// and also return T | |
T getValue() { | |
return value; | |
} | |
void exampleUse() { | |
// This is how you use the generic type | |
Wrapper<String> s = new Wrapper<>("Hello"); | |
s.doSomething("World"); | |
System.out.println(s.getValue()); | |
// This is the same with another type | |
Wrapper<Integer> i = new Wrapper<>(42); | |
i.doSomething(43); | |
System.out.println(i.getValue()); | |
// or even nested | |
Wrapper<Wrapper<String>> w = new Wrapper<>(new Wrapper<>("Hello")); | |
w.doSomething(new Wrapper<>("World")); | |
System.out.println(w.getValue().getValue()); | |
} | |
} | |
// Variance works with the keywords extends and super | |
// In class declaration this means T must be a subtype of Number | |
// for more see here: https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science) | |
// https://stackoverflow.com/questions/26360259/scala-arguments-contravariant-and-return-types-are-covariant-why | |
class Variance<T extends Number> { | |
// Covariance works the following: | |
// T and Number are classes | |
// if T is a subtype of Number then | |
// Wrapper<T> is a subtype of Wrapper<Number> | |
void covariance(Wrapper<? extends T> w) { | |
// ... | |
} | |
// Contravariance works the following: | |
// T and Number are classes | |
// if T is a subtype of Number then | |
// Wrapper<Number> is a subtype of Wrapper<T> | |
void contravariance(Wrapper<? super T> w) { | |
// ... | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment