Thinking in java

1 OOP

Modules Terms  Description
Object Oriented Programmming (OOP)  Encapsulation
  1. public
  2. protected
  3. private

The object encapsulates variables and methods, some of which are exposed to the outside, while others are not.

Inheritance

You can use "extends" to single-inherit a parent class.

Abstraction

Circles, triangles, rectangles, and other shapes can be abstracted into a class called "Shape," as they are all shapes.

Polymorphism

circle, triangle, rectangle can use shape to execute functions.

Shape shape = new Circle(); // Triangle(); Rectangle();

shape.size(); 

This makes programming more convenient, so you don't have to create a new object every time there's a new shape and then call the size() method.

 

2 Method overloading

The method signature is defined only by its name and parameters, not by its return type.

1 public class Print{
2 
3     void print(){};
4     void print(int i){};
5

3 Constructor 

Default Constructor If a constructor is explicitly written in the code, the program will not create a default constructor. Otherwise, there will be a default constructor
Code

The code to call another constructor must be placed on the first line and can only be used once.

public Constructor(int i){
      Constructor();
      .....
}

 

this reference 

this can only be used inside a class.
You cannot write this inside a static context, because the object may not have been constructed yet.

 4. Initialization

1) Initialization order of non-static data:

  • Member variables (regardless of where they are written, such as before or after methods)

  • Method block {}

  • MethodsInitialization of static data:

2) static data

  • Static data occupies only one storage area.

  • static cannot be applied to local variables.

  • Initialization process: static first, then non-static.

  • Static members are loaded as the class is loaded.

  • Initialized in order.

5 Array

new Object[] {new Integer(0), new Float(1.0), new Double(1.0)}

void printArrs(Object ... args){
  for(Object arg : args) ..  
}

6 Access Control:

Key Words   Range
public  Everywhere
private

Except for the class that contains the member, no other class can access it.

protected Used to handle inheritance. In a subclass, protected members can be accessed. protected also provides package-level access.
Package Access

Without any modifier, it can only be used within the same package directory.

For class access: Only one public class is allowed per file. A class cannot be declared as private or protected. If you want to prevent others from accessing the class, you can declare its constructor as private

7. Locations for Initializing Reference Objects

1)  At the point of definition

public class MyClass {
    private List<String> list = new ArrayList<>(); // initialized at definition
}

2)  In the class constructor

public class MyClass {
    private List<String> list;

    public MyClass() {
        list = new ArrayList<>(); // initialized in constructor
    }
}

3)  Lazy initialization

public class MyClass {
    private List<String> list;

    public List<String> getList() {
        if (list == null) {
            list = new ArrayList<>(); // lazy initialization
        }
        return list;
    }
}

4)  Instance initialization block

public class MyClass {
    private List<String> list;

    { // instance initialization block
        list = new ArrayList<>();
        System.out.println("List initialized");
    }
}

8 If the constructor of the current class conflicts with the parent class, this problem can be resolved through another constructor

public class Dog extends Animal {
    private String breed;

    // Constructor 1: calls parent constructor directly
    public Dog(String name, String breed) {
        super(name); // resolves conflict by explicitly calling parent constructor
        this.breed = breed;
    }

    // Constructor 2: calls another constructor in the same class using this()
    public Dog(String name) {
        this(name, "Unknown"); // delegates to Constructor 1
    }

    // Constructor 3: provides default values
    public Dog() {
        this("Unknown", "Unknown"); // also delegates
    }
}

public class Animal {
    private String name;

    public Animal(String name) { // no default constructor
        this.name = name;
    }
}

9 Clean

class Parent {
    void show() {
        System.out.println("Parent show()");
    }

    void show(String msg) {
        System.out.println("Parent show: " + msg);
    }
}

class Child extends Parent {
    // Overloading: adds a new version, does not hide parent's overloaded methods
    void show(int number) {
        System.out.println("Child show: " + number);
    }
}

public class Test {
    public static void main(String[] args) {
        Child obj = new Child();

        obj.show();              // ✅ Calls Parent's show()
        obj.show("Hello");       // ✅ Calls Parent's show(String)
        obj.show(100);           // ✅ Calls Child's show(int)
    }
}

10 Override

"The access level of the overriding method must be greater than or equal to the access level of the parent class method."

class Parent {
    protected void display() {
        System.out.println("Parent display");
    }
}

class Child extends Parent {
    @Override
    public void display() { // ✅ allowed (protected → public)
        System.out.println("Child display");
    }
}

 

class Child2 extends Parent {
    @Override
    void display() { // ❌ compilation error (protected → default is not allowed)
        System.out.println("Child display");
    }
}

 

11 final

  • Modify data: a constant that will never change.

  • Modify data: blank final — must be initialized before it is used.

  • Final parameter: the parameter value cannot be modified.

  • Modify reference variables: the reference itself cannot change; the memory address remains the same.

  • Modify methods: a method is declared final when it must not be overridden.

  • All private methods in a class are implicitly final.

  • Final class: a class that is not intended to be inherited; it cannot have subclasses.

12 Pitfalls of Overriding

If a parent class method f() is private, and the subclass defines a public method f(), polymorphism will still call the parent's f()

Variables are not overridden 

class Parent {
    String name = "Parent";
}

class Child extends Parent {
    String name = "Child"; // hides parent's name, but not override
}

public class Test {
    public static void main(String[] args) {
        Parent obj = new Child();
        System.out.println(obj.name); // Output: Parent (not Child)
    }
}

13 Inheritance and Cleanup

Initialization from top to bottom, destruction from bottom to top — be careful when destroying objects

14 Behavior of Polymorphic Methods Inside Constructors

If the subclass is not fully initialized, the parent class may polymorphically call the subclass's methods

public class Main {
    public void draw(){
        System.out.println("Main draw");
    }

    public Main(){
        System.out.println("Main() ");
        draw();
    }

    public static void main(String [] args){
        new Sub();
    }
}


public class Sub extends Main{
    private int v = 1;

    public void draw(){
        System.out.println("sub draw() " + v);
    }
    Sub(){
        System.out.println("Sub() " + v);
    }
}

/*

Main()
sub draw() 0
Sub() 1

*/

 

Inside constructors, try to avoid using other methods whenever possible. If you must use them, use final or private methods.

 

15 Abstract Classes and Abstract Methods

  • Abstract Classes Cannot Be Instantiated
  • Provide common methods, Better extensibility — Define a template for subclasses,Enable polymorphism  
  • abstract is the key word\

16 Interface

  • interface  produces a completely abstract class
  • Interfaces define a contract between classes
  • Fields in Interfaces are static, final, public
public interface Action {
    void doSth();
    void height();
}

class Creature implements Action {
    public void doSth(){
        System.out.println("creature doSth");
    }

    public void height(){
        System.out.println("creature height");
    }
}


class Human extends Creature{
    public void doSth(){
        System.out.println("human doSth");
    }

    public static void main(String [] args){
        Action a = new Human();
        a.doSth();
        a.height();
    }
}

 

17 Inner Class

  • Inner Classes Can Directly Communicate with Outer Class
  • Referring to Outer Class: OuterClass.this 
  • Creating Inner Class: outer.new Inner() 
  • Cannot Create Inner Class Without Outer Instance
  • If the inner class is private, it cannot be created outside the outer class.

18 (Anonymous Inner Class)

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


public class Main {
     public Contents contents(){
         return new Contents(){
             private int i = 11;
             public int value(){return i;}
         };
    }

    public static void main(String [] args){
         Main m = new Main();
         Contents c = m.contents();
         c.value();
    }
}

interface Contents{
    int value();
}

  

abstract class Base {
    public Base(int i ){

    }
    public abstract void f();
}

class AnonymousConstructor{
    public static Base getBase(int i ){
        return new Base(i){
            public void f(){

            }
        };
    }
    public static void main(String [] args){
        Base b = getBase(1);
        b.f();;
    }
}

 

Local variables (explicit final)abstract class Base {
    public Base(final int i ){

    }
    public abstract void f();
}

class AnonymousConstructor{
    public Base base(final int i ){
        return new Base(i){
            private int num;
            {
                num = 1000;
            }
            public void f(){
                System.out.println(num);
            }
        };
    }

}

Cannot Extend and Implement Simultaneously 

19 Classes inside an interface

In Java, you can define nested classes inside an interface. This is a powerful feature for grouping related functionality together.

20 Type casting 

  • Upcasting (Automatic, Safe) 
  • Downcasting (Risky, Requires Explicit Cast) instanceof

21 instanceof & Class 

  • instanceof for Upcasting, .class and == for Exact Type Comparison

21 Reflection: Runtime Type Information

  • Loading Classes Across Network

22 Dynamic Proxy in Java

  • The target object must implement at least one interface (Java's java.lang.reflect.Proxy class can only create proxies for interfaces, not classes.) AOP design

23 Generics in Java

  • Type Erasure, ArrayList.class is OK, but ArrayList<String>.class is not.

24 Bounds in Generics

  1. the class must come first, followed by interfaces.
class ColoredDimension<T extends Dimension & HasColor>
  • at most one class, can have multiple interfaces

25 The File Class

  • Can represent both directories and files
package com.webbuild.controllers;

import java.io.File;

public class FileTest {
    public static void main(String [] args){
        File f = new File("D:\\");
        for(String s : f.list()) System.out.println(s);
    }
}

26 Input and output in Java

  • FileInputStream and Batch Reading

package com.webbuild.controllers;

import java.io.File;
import java.io.FileInputStream;

public class FileTest {
    public static void main(String [] args) throws Exception{
        File f = new File("D:\\ff.txt");
        FileInputStream fis = new FileInputStream(f);
        byte [] readBuf = new byte[512];
        int len = fis.read(readBuf);
        for(int i = 0; i < len; i++){
            System.out.println((char)readBuf[i]);
        }

    }
}

27 Reader and Writer in Java

  • Internationalization with Unicode
  • BufferedReader可以readLine
public static void main(String [] args) throws Exception{
        FileReader fr = new FileReader("D:\\ff.txt");
        BufferedReader br = new BufferedReader(fr);
        String line;
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }
        br.close();
        fr.close();
    }

28. Enums in Java

  • Cannot extend classes
  • Singleton pattern, each enum constant is a single instance
  • Can import enum constants for cleaner code 
  • Enum constructors are private or package-private 
  • Enums are final by default
package com.webbuild.controllers;

public interface Food {
    enum Appetizer implements Food{
        SALAD, SOUP;
    }
    
    enum Coffee implements Food{
        BLACK_COFFEE, LATTE, TEA
    }
}

 

29 Annotations in Java

  • Allowed Element Types: Primitive types, String, Class, Enum, Annotation, Arrays
package com.webbuild.controllers;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
    
}
  • @Traget. Where the annotation can be applied
  • @Retention. How long the annotation is retained
  • @Documented. Include annotation in JavaDoc
  • @Inherited. Allow subclasses to inherit the annotation

 

 Four meta-annotations control how annotations behave:

 

30 Concurrent.

  • Parallelism: Multiple processors executing simultaneously
  • Concurrency: Multiple tasks making progress in overlapping time periods
  • Thread Class, only call start to run thread, if you run run() function, it doestn't execute concurrently 

31 Ways to Create Threads in Java

  1. Extend Thread
  2. Implement Runnable, no return value
  3. Implement Callable

Thread Yielding Thread voluntarily gives up CPU to other threads

Thread.yeald();

Thread Pool, don't need to create a thread every time.

  • ExecutorService

future blocks until completion

32 Sleep

TimeUnit.SECONDS.sleep() 

  • Will yield CPU execution rights
  • Will not release locks 

33 Thread Priority

  • Deamon Threads - Threads provide general services in backgroud. They are not essential.
  • Non-Deamon Threads - Essential Threads. main()
  • Daemon threads do not execute finally blocks when terminating
  • t2.join() causes the current thread to pause execution until thread t2 terminates

34 Shared Limited Resources

Bullets Description Code
The static keyword represents shared resources

static means there is only one copy in the program, therefore it is a shared resource

 

boolean is atomic

It is atomic, requiring only a single machine instruction

 

Increment and decrement operations are not atomic

   

Locking prevents other threads from accessing

Acquire lock, execute, release lock. This mechanism is often called mutual exclusion or mutex

 
synchronized    
Every object automatically contains a lock    

For a specific object, all synchronized blocks share the same lock

When a thread executes synchronized f(), no other threads can execute g()

package learnjava;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class SychronizedTest {
    public static void main(String [] args) throws InterruptedException{
        TaskRunner taskRunner = new TaskRunner(new Object());
        ExecutorService service = Executors.newFixedThreadPool(4);
        for(int i = 0; i < 100; i++){
            service.execute(taskRunner);
        }
        service.shutdown();
        TimeUnit.SECONDS.sleep(1);
    }


}
class TaskRunner implements Runnable{
    private int count = 0;
    private Object obj;

    public TaskRunner(Object obj){
        this.obj = obj;
    }
    public void run(){
        synchronized (obj){
            count++;
            System.out.println(count);
        }
    }
}

 

A synchronized non-static method actually locks on 'this'

 
public synchronized void run()

 

Reentrant Lock

 
 A task can acquire an object's lock multiple times without needing to compete again. When a thread re-acquires the lock, the counter increments by 1. When a task exits, the counter decrements. Sychronized is reentrant.  
public class ReentrantCounterExample {
    private final ReentrantLock lock = new ReentrantLock();
    
    public void methodA() {
        lock.lock();     // First acquisition: hold count = 1
        System.out.println("Hold count: " + lock.getHoldCount()); // 1
        try {
            methodB();   // Same thread re-enters
            // Do work
        } finally {
            lock.unlock(); // First release: hold count = 0
        }
    }
    
    public void methodB() {
        lock.lock();     // Second acquisition: hold count = 2
        System.out.println("Hold count: " + lock.getHoldCount()); // 2
        try {
            methodC();   // Can re-enter again
            // Do more work
        } finally {
            lock.unlock(); // Second release: hold count = 1
        }
    }
    
    public void methodC() {
        lock.lock();     // Third acquisition: hold count = 3
        System.out.println("Hold count: " + lock.getHoldCount()); // 3
        try {
            // Do even more work
        } finally {
            lock.unlock(); // Third release: hold count = 2
        }
    }
}

 

 

The lock for a synchronized static method is not the 'this' lock, but rather the Class object lock (ClassName.class) Multiple threads running the same class's static synchronized methods: only one thread can execute, BUT synchronized methods (non-static, and locking on different instances) can execute simultaneously  
package com.wn.rest.concurrent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class LearnSync extends Thread {
    private static int count = 0;

    public LearnSync() {
    }

    public synchronized static void out() {
        System.out.println("Ready to start thread " + Thread.currentThread().getName());
        try {
            while (true) {
                count++;
                System.out.println("in static " + Thread.currentThread().getName() + " count " + count);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    

    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(4);
        for (int i = 0; i < 4; i++) {
            service.execute(new Runnable() {
                @Override
                public void run() {
                    LearnSync.out();
                }
            });
        }
        
        service.shutdown();
    }
}

 35 Lock

Bullets Description Code
Lock Finer granularity. If something fails inside synchronized, you cannot do finer-grained things, such as performing cleanup work in finally
package learnjava;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockTest {
    public static void main(String [] args){
        ExecutorService service = Executors.newFixedThreadPool(10);
        RunnableTask runnableTask = new RunnableTask();
        for(int i = 0; i < 100; i++){
            service.execute(runnableTask);
        }
        service.shutdown();
    }
}

class RunnableTask implements Runnable{
    public int count = 100;
    private Lock lock = new ReentrantLock();

    public void run(){
        lock.lock();
        //防止执行模块异常 无法释放锁
        try {
            count--;
            System.out.println("count " + count);
        } finally {
            lock.unlock();
        }

    }
}

 

  tryLock in Lock attempts to acquire the lock and will continue executing the following code (whether successful or not). lock() will wait indefinitely until the lock is acquired.  
import java.util.concurrent.locks.ReentrantLock;

public class TryLockVsLock {
    private final ReentrantLock lock = new ReentrantLock();
    
    public void useLock() {
        System.out.println(Thread.currentThread().getName() + " trying to lock");
        
        lock.lock();  // <-- BLOCKS HERE until lock is acquired
        // Thread waits HERE indefinitely until it gets the lock
        
        try {
            System.out.println(Thread.currentThread().getName() + " got the lock");
            Thread.sleep(2000);  // Hold lock for 2 seconds
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
            System.out.println(Thread.currentThread().getName() + " released lock");
        }
    }
    
    public void useTryLock() {
        System.out.println(Thread.currentThread().getName() + " trying tryLock");
        
        boolean gotLock = lock.tryLock();  // <-- RETURNS IMMEDIATELY, never blocks!
        
        if (gotLock) {
            try {
                System.out.println(Thread.currentThread().getName() + " got the lock with tryLock");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
                System.out.println(Thread.currentThread().getName() + " released lock");
            }
        } else {
            // This code executes IMMEDIATELY if lock is not available
            System.out.println(Thread.currentThread().getName() + 
                             " could NOT get lock, but still executing!");
            // Do alternative work
        }
    }
}

 

 

36 Atomicity and Volatility

Bullets Description Code
Atomicity

Atomic operations are operations that cannot be interrupted by the thread scheduling mechanism. Once started, they will execute to completion without being interrupted in the middle.

This applies to basic operations on primitive types except long and double. The JVM splits 64-bit long and double into two 32-bit operations.

 

 
Visibility

Reads occur from main memory, writes are temporarily written to memory

 
volatile

The volatile keyword immediately writes content to main memory. The synchronized keyword can guarantee visibility. If a field is modified by the synchronized keyword, then it does not need to be modified by volatile. Any write operations by a task are visible to that task. It guarantees atomicity and visibility. Both reads and writes should be synchronized.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class AtomicTest implements Runnable{
    private int i = 0;
    private synchronized void add(){
        i++;
        i++;
    }

    public synchronized int get(){
        return i;
    }
    public void run(){
        while (true){
            add();
        }
    }

    public static void main(String [] args){
        AtomicTest atomicTest = new AtomicTest();
        ExecutorService service = Executors.newFixedThreadPool(10);
        service.execute(atomicTest);
        while (true){
            int num = atomicTest.get();
            if(num % 2 != 0){
                System.out.println(num);
                System.exit(0);
            }
        }

    }
}

 

 
 AtomicInteger    
Thread States:

 

    • NEW: Created but not started

    • RUNNABLE: Executing or ready to execute

    • BLOCKED: Waiting for monitor lock

    • WAITING: Waiting indefinitely for another thread

    • TIMED_WAITING: Waiting for a specified time

    • TERMINATED: Completed execution

 
 ThreadLocal

ThreadLocal provides thread-local variables — each thread accessing such a variable has its own, independently initialized copy of the variable.

 

Each Thread has its own ThreadLocals, it is a map. So it is thread isolated.

 

// java.lang.ThreadLocal 类
public void set(T value) {
    // 1. 获取当前线程
    Thread t = Thread.currentThread();
    
    // 2. 获取当前线程的 ThreadLocalMap
    ThreadLocalMap map = getMap(t);
    
    // 3. 如果 map 存在,就把值放进去
    if (map != null)
        // 注意:key 是 this(当前 ThreadLocal 对象)
        map.set(this, value);
    else
        // 第一次调用,创建 map
        createMap(t, value);
}

// 获取当前线程的 ThreadLocalMap
ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;  // 每个线程自己的 map
}

// 创建 ThreadLocalMap
void createMap(Thread t, T firstValue) {
    // key 是 this,value 是传入的值
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

 

public class ConnectionManager {
    private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>() {
        @Override
        protected Connection initialValue() {
            return DriverManager.getConnection(DB_URL);
        }
    };
    
    public static Connection getConnection() {
        return connectionHolder.get();  // Each thread gets its own connection
    }
    
    public static void closeConnection() {
        Connection conn = connectionHolder.get();
        if (conn != null) {
            conn.close();
            connectionHolder.remove();
        }
    }
}

// Usage
public class TransactionalService {
    public void doWork() {
        Connection conn = ConnectionManager.getConnection(); // Thread-specific
        // Use connection - no interference from other threads
    }
}

 

 

 

  

 
 
 
 
posted @ 2023-09-24 08:59  ylxn  阅读(81)  评论(0)    收藏  举报