Java 学习记录

7.16'21

介绍

Java 是通用,并发,基于类,面向对象的编程语言。

Java is a general-purpose, concurrent, class-based, object-oriented computer programming language.

https://learnxinyminutes.com/docs/java/

安装、运行

安装完成后,可以使用java命令

新建文件LearnJava.java,可以直接编译运行

public class LearnJava {
    public static void main(String[] args) {
        System.out.println("Hello world!");
    }
}
java LearnJava.java

基本语法

Access Modifiers

Helps to restrict the scope of a class, constructor, variable, method or data member.

defaultprivateprotectedpublic
Same ClassYesYesYesYes
Same package subclassYesNoYesYes
Same package non-subclassYesNoYesYes
Different package subclassNoNoYesYes
Different package non-subclassNoNoNoYes
  • private: only in same class
  • default: only in same package
  • protected: same package or subclass
  • public: anywhere

Import

使用import引入其它包的类、方法或变量

import java.util.ArrayList;

Comment

// Single-line comments

/*
 * Multi-line comments
 */

Output/Input

System.out.println("Hello World!");
import java.util.Scanner;
Scanner scanner = new Scanner(System.in);
String name = scanner.next();

Variables

type name = value;

// Declaration
int fooInt;
int fooInt1, fooInt2, fooInt3;

// Initialization
int barInt = 1;

Numbers

// 8-bit signed, -128 <= byte <= 127
byte fooByte = -100; 

// 16-bit signed, -32,768 <= short <= 32,767
short fooShort = 10000;

// 32-bit signed, -2,147,483,648 <= int <= 2,147,483,647
int bazInt = 1;

// 64-bit signed
// -9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807
long fooLong = 100000L;

// 32-bit single-precision
float fooFoloat = 234.5f;

// 64-bit double-precision
double fooDouble = 124.4;

// Boolean - true & false
boolean fooBoolean = true;
boolean barBoolean = false;

// Char - A single 16-bit Unicode character
char fooChar = 'A';
// Final variables can't be reassigned, 
// but they can be initialized later.
final int hours_i_work_per_week = 9001;

final double E;
E = 2.71828;
import java.math.BigInteger;
import java.math.BigDecimal;
// BigInteger - Immutable arbitrary-precision integers
BigInteger fooBigInteger = new BigInteger("1234567890");

// BigDecimal - Immutable arbitrary-precision signed decimal number
BigDecimal fooBigDecimal = new BigDecimal("0.1");

Strings

String fooString = "My string is here";
String barString = "Printing on a new line?\n\tNo problem!";

String building

String plusConcatenated = "String can " + "be concatenated" + "via + operator.";

StringBuilder builder = new StringBuilder();
builder.append("you ");
builder.append("can use ");
builder.append("the StringBuilder class.");
// Only now is the string built
System.out.println(builder.toString());

String formatted = String.format("%s may prefer %s.", "Or you", "String.format()");
System.out.println(formatted);

Arrays

// Declare an array
// type[] name = new type[size]
// type name[] = new type[size]
int[] intArray = new int[10];
String[] stringArray = new String[1];
boolean boolArray[] = new boolean[100];

// declare and initialize an array
int[] nums = {9000, 1000, 1337};
String names[] = {"Bob", "John", "Fred", "Juan Pedro"};
boolean bools[] = {true, false, false};

// Indexing an array - Access an element
System.out.println("Num @0: " + nums[0]);
// Arrays are zero-indexed and mutable
nums[1] = 2000;
System.out.println("Num @1: " + nums[1]);

Other data types

  • ArrayList

    Like arrays. The size is mutable.

  • LinkedList

    Implementation of doubly-linked list.

  • Map

    A mapping of key Objects to value Objects. Map is an interface.

  • HashMap

    This class uses a hashtable to implement the Map interface.

  • TreeMap

    A Map that is sorted by its keys.

Operators

// Arithmetic is straightforward
System.out.println("1 + 2 = " + (i1 + i2));
System.out.println("2-1 = " + (i2 - i1));
System.out.println("2*1 = " + (i2 * i1));
System.out.println("1/2 = " + (i1 / i2)); // => 0
System.out.println("1/2.0 = " + (i1 / (double)i2));

// Modulo
System.out.println("11%3 = " + (11 % 3));

// Comparison
System.out.println("3 == 2? " + (3 == 2));
System.out.println("3 != 2? " + (3 != 2));
System.out.println("3 > 2? " + (3 > 2));
System.out.println("3 < 2? " + (3 < 2));
System.out.println("2 <= 2? " + (2 <= 2));
System.out.println("2 >= 2? " + (2 >= 2));

// Boolean
System.out.println("3 > 2 && 2 > 3? " + ((3 > 2) && (2 > 3)));
System.out.println("3 > 2 || 2 > 3? " + ((3 > 2) || (2 > 3)));
System.out.println("!(3 == 2)? " + (!(3 == 2)));

// Bitwise oeprators
/*
 * ~    Unary bitwiase complement
 * <<   Signed left shift
 * >>   Signed/Arithmetic right shift
 * >>>  Unsigned/Logical right shift
 * &    Bitwise AND
 * ^    Bitwise exclusive OR
 * |    Bitwise inclusive OR
 */

// Increment operators
int i = 0;
System.out.println(i++);
System.out.println(--i);

Control Structures

If

if (condition) { statements }
int j = 10;
if (j == 10) {
    System.out.println("I get printed");
} else if (j > 10) {
    System.out.println("I don't");
} else {
    System.out.println("I also don't");
}

'?' operator

int foo = 5;
System.out.println("Foo: " + (foo < 10 ? "A" : "B"));

While

while (condition) { statements }
// While loop
int foo = 0;
while(foo < 100) {
    foo++;
}

// Do While loop
int foo = 0;
do {
    foo++;
} while (foo < 100);

For

for (start; condition; step) { statements }
for (int i = 0; i < 10; i++) {
    System.out.println(i);
}

// Nested For loop exits with Label
outer: 
for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
        if (i == 5 && j == 5) {
            // breaks out of outer loop instead of only
            // the inner one
            break outer;
        }
    }
}

For each

for (element : iterable) { statements }
int[] list = {1, 2, 3, 4, 5, 6, 7, 8, 9};

for (int foo : list) {
    System.out.println(foo);
}

Switch case

int month = 3;
String monthString;
switch (month) {
    case 1: monthString = "January";
            break;
    case 2: monthString = "February";
            break;
    case 3: monthString = "March";
            break;
    default: monthString = "Some other month";
             break;
}
System.out.println("Result: " + monthString);

Try-with-resources

// Try-with-resources closes resources automatically
try (BufferedReader br = new BufferedReader(new FileReader("pom.xml"))) {
    System.out.println(br.readLine());
} catch (Exception e) {
    System.out.println("readLine() failed");
}

Converting Data Types

Integer.parseInt("123") // => 123
Integer.toString(123)   // => "123"

Classes and Functions

Class syntax

<private|protected|public> class <name> {
    // data fields, constructors, functions(methods) all inside.
}

Method syntax

<private|protected|public> <return type> <name>(<args>)

Instantiate

// Use new to instantiate a class
Bicycle trek = new Bicycle();

// Call object methods
trek.speedUp(3);
trek.setCadence(100);
System.out.println("Trek info: " + trek.toString());

Define class

class Bicycle {
    public int cadence; // Anywhere
    private int speed;  // Only within the class
    protected int gear; // Only from the class or subclasses
    String name;        // Default: Only within the package

    // Static class variable
    static String className; 

    // Static block that can be used to initialize static variables
    static {
        className = "Bicycle";
    }

    // Constructors are a way of creating classes
    // This is a constructor
    public Bicycle() {
        // You can also call another constructor: 
        // this(1, 50, 5, "Bontrager");
        gear = 1;
        cadence = 50;
        speed = 5;
        name = "Bontrager";
    }
    // This is a constructor that takes arguments
    public Bicycle(int startCadence, int startSpeed, int startGrea, 
            String name) {
        this.gear = startGrea;
        this.cadence = startCadence;
        this.speed = startSpeed;
        this.name = name;
    }

    // Classes often implement getters and setters for their fields
    public int getCadence() {
        return cadence;
    }
    public void setCadence(int newValue) {
        cadence = newValue;
    }
    public void setGear(int newValue) {
        gear = newValue;
    }

    public void speedUp(int increment) {
        speed += increment;
    }
    public void slowDown(int decrement) {
        speed -= decrement;
    }

    public void setName(String newValue) {
        name = newValue;
    }
    public String getName() {
        return name;
    }

    @Override 
    public String toString() {
        return "Gear: " + gear + " cadence: " + cadence + 
            " speed: " + speed + " name: " + name;
    }
}

@Override: Compilers are required to generate an error unless the method does override or implement a method declared in supertype

Subclass

使用extends创建 subclass。

// PennyFarthing is a subclass of Bicycle
class PennyFarthing extends Bicycle {
  public PennyFarthing(int startCadence, int startSpeed) {
    super(startCadence, startSpeed, 0, "PennyFarthing");
  }

  @Override
  public void setGear(int gear) {
    this.gear = 0;
  }
}

Object casting - 子类的实例可以赋值给基类。

// Object casting
// We can say a PennyFarting is a Bicycle
Bicycle bicycle = new PennyFarthing(50, 5);
System.out.println("Bicycle info: " + bicycle.toString());

Interface

Interface declaration syntax

<access-level> interface <interface-name> extends <super-interfaces> {
    // Constants
    // Method declarations
}
// Example - Food:
public interface Edible {
    public void eat(); // Any class that implements this interface, must
                       // implement this method.
}

public interface Digestible {
    public void digest();
    // Since Java 8, interfaces can have default method.
    public default void defaultMethod() {
        System.out.println("Hi from default method ...");
    }
}

// We can now create a class that implements both of these interfaces.
public class Fruit implements Edible, Digestible {
    @Override
    public void eat() {
        // ...
    }

    @Override
    public void digest() {
        // ...
    }
}

You can implement many interfaces

public class ExampleClass implements InterfaceOne, InterfaceTwo {
    @Override
    public void InterfaceOneMethod() {
    }

    @Override
    public void InterfaceTwoMethod() {
    }

}

Abstract classes

Abstract Class declaration syntax

<access-level> abstract class <abstract-class-name> extends
<super-abstract-classes> {
    // Constants and variables
    // Method declarations
}
  • Abstract Classes cannot be instantiated.
  • Abstract classes may define abstract methods.
  • Abstract methods have no body and are marked abstract
  • Non-abstract child classes must @Override all abstract methods from their super-classes.
public abstract class Animal {
    private int age;

    public abstract void makeSound();

    // Method can have a body
    public void eat()
    {
        System.out.println("I am an animal and I am Eating.");
        // Note: We can access private variable here.
        age = 30;
    }

    public void printAge()
    {
        System.out.println(age);
    }

    // Abstract classes can have main method.
    public static void main(String[] args)
    {
        System.out.println("I am abstract");
    }
}

class Dog extends Animal {
    // Override the abstract methods in the abstract class.
    @Override
    public void makeSound()
    {
        System.out.println("Bark");
        // age = 30;    ==> ERROR!    age is private to Animal
    }

    // What is happening here is called METHOD HIDING.
    public static void main(String[] args)
    {
        Dog pluto = new Dog();
        pluto.makeSound();
        pluto.eat();
        pluto.printAge();
    }
}

Final Classes

Final Class declaration syntax

<access-level> final <final-class-name> {
    // Constants and variables
    // Method declarations
}

Final classes are classes that cannot be inherited from and are therefore a final child. In a way, final classes are the opposite of abstract classes because abstract classes must be extended, but final classes cannot be extended.

public final class SaberToothedCat extends Animal
{
    // Note still have to override the abstract methods in the
    // abstract class.
    @Override
    public void makeSound()
    {
        System.out.println("Roar");
    }
}

// Final Methods
public abstract class Mammal()
{
    // Final Method Syntax:
    // <access modifier> final <return type> <function name>(<args>)

    // Final methods, like, final classes cannot be overridden by a child
    // class, and are therefore the final implementation of the method.
    public final boolean isWarmBlooded()
    {
        return true;
    }
}

Enum Type

An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it.

Because they are constants, the names of an enum type's fields are in uppercase letters. In the Java programming language, you define an enum type by using the enum keyword.

For example, you would specify a days-of-the-week enum type as:

public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, 
    THURSDAY, FRIDAY, SATURDAY
}

public class EnumTest  {
    Day day;

    public EnumTest(Day day) {
        this.day = day;
    }

    public void tellItLikeItIs() {
        switch (day) {
            case MONDAY: 
                System.out.println("Mondays are good.");
                break;
            case FRIDAY: 
                System.out.println("Fridays are better.");
                break;
            case SATURDAY: 
            case SUNDAY: 
                System.out.println("Weekends are best.");
                break;
            default: 
                System.out.println("Midweek days are so-so.");
                break;
        }
    }

    public static void main(String[] args) {
        EnumTest firstDay = new EnumTest(Day.MONDAY);
        firstDay.tellItLikeItIs();

        EnumTest thirdDay = new EnumTest(Day.WEDNESDAY);
        thirdDay.tellItLikeItIs();
    }
}

Lambda

Syntax

<zeor or more parameters> -> <expression body or statement block>
public class LambdaTest {
  public static void main(String[] args) {
    Map<String, String> planets = new HashMap<>();
    planets.put("Mecury", "87.969");
    planets.put("Venus", "224.7");
    planets.put("Earth", "365.2564");
    planets.put("Mars", "687");
    planets.put("Jupiter", "4,332.59");
    planets.put("Saturn", "10,759");
    planets.put("Uranus", "30,688.5");
    planets.put("Neptune", "60,182");

    Supplier<String> numPlanets = () -> Integer.toString(planets.size());

    System.out.format("Number of Planets: %s\n\n", numPlanets.get());

    // Lambda ways
    planets.keySet().forEach(p -> System.out.format("%s\n", p));

    String orbits = "%s orbits the Sun in %s Earth days.\n";
    planets.forEach((k, v) -> System.out.format(orbits, k, v));

    // Traditional ways
    for (String planet : planets.keySet()) {
      System.out.format("%s\n", planet);
    }

    for (String planet : planets.keySet()) {
      System.out.format(orbits, planet, planets.get(planet));
    }
    for (Map.Entry<String, String> planet : planets.entrySet()) {
        System.out.format(orbits, planet.getKey(), planet.getValue());
    }
  }
}
📖