Skip to content

Java指南(一)

🕒 Posted at: 2020-11-01 ( 4 years ago )
Java
JDK/JRE组成、基础语法、面向对象特性(如类、继承、多态)、关键字使用(static、final)、高级特性(接口、内部类、枚举、抽象类)及现代Java特性(Lambda表达式、方法引用)。

JDK的组成

JDK是Java Development Kit的缩写, 由JVM、核心类库、开发工具包组成。

JRE是Java Runtime Environment的缩写,由JVM和核心类库组成。

开发工具包包含了编译工具、调试工具、性能分析工具等。例如:javac、java、javadoc、jdb等。

Hello World

java
package org.example;

public class Main {
    public static void main(String[] args) {
    
        System.out.printf("Hello and welcome!");
        
        for (int i = 1; i <= 5; i++) {
            System.out.println("i = " + i);
        }
    }
}

方法重载

方法重载是指在一个类中,多个方法具有相同的名字,但参数列表不同的情况。

  • 参数列表不同:参数的个数不同,参数的类型不同,参数的顺序不同。
  • 返回值类型不同:方法的返回值类型不同,不能通过返回值类型来区分方法。
  • 仅仅通过参数名的不同是不能构成方法的重载的。
java
package org.example;

public class Main {
    public static void main(String[] args) {

        // say hello
        System.out.println(sayHello());

        // say hello to someone
        System.out.println(sayHello("Alice"));

        // say hello to someone with a title
        System.out.println(sayHello("Dr", "Bob"));

    }

    // say hello
    public static String sayHello() {
        return "Hello";
    }

    // say hello to someone
    public static String sayHello(String name) {
        return "Hello " + name;
    }

    // say hello to someone with a title
    public static String sayHello(String title, String name) {
        return "Hello " + title + " " + name;
    }
}

数组

数组的定义

数组是相同类型数据的有序集合,数组中的每个数据称为元素,每个元素可以通过一个索引来访问。

java
public class Main {
    public static void main(String[] args) {

        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }

        var arr2 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        for (int i = 0; i < arr2.length; i++) {
            System.out.println(arr2[i]);
        }

        var arr3 = new int[10]; // 10 is the size of the array

        for (int i = 0; i < arr3.length; i++) {
            System.out.println(arr3[i]);
        }
    }
}

数组反转

java
public class Main {
    public static void main(String[] args) {

        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }

        for (int i = 0, j = arr.length-1; i < j; i++, j--) {
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }

        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

类的创建

java
package org.example;

class Person {
    private  String name;
    private  int age;

    // constructor with parameters
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // constructor without parameters
    public Person() {
        this.name = "Unknown";
        this.age = 0;
    }

    public String getName() {
        return name;
    }

    // set name
    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    // set age
    public void setAge(int age) {
        this.age = age;
    }

    public void print() {
        System.out.println("Name: " + name + ", Age: " + age);
    }
}

public class Main {
    public static void main(String[] args) {

        Person p1 = new Person("John", 30);
        p1.print();  // Name: John, Age: 30

        Person p2 = new Person();

        p2.print();  // Name: Unknown, Age: 0
        p2.setName("Doe");
        p2.setAge(25);

        p2.print();  // Name: Doe, Age: 25

    }
}

实体JavaBean

实体JavaBean是一个公共类,它具有私有属性,并通过公共方法来设置和获取这些属性。还必须有一个无参构造函数。

java
package org.example;

public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

应用场景:

实体JavaBean通常用于数据传输对象(DTO),数据访问对象(DAO)等。也就是只负责数据的存储和读取,不包含业务逻辑。业务逻辑交给其他类处理,以保证数据和业务逻辑的分离。

String

创建字符串

java
public class Main {
    public static void main(String[] args) {

        String str1 = new String();

        String str2 = "Hello";

        char[] char1 = {'', '', ''};

        String str3 = new String(char1);

        System.out.println(str1);

        System.out.println(str2);

        System.out.println(str3);
    }
}

遍历字符串

java
String str1 = "Hello";

for (int i = 0; i <str1.length() ; i++) {
    System.out.println(str1.charAt(i));
}

char[] charArray = str1.toCharArray();

for (char c : charArray) {
    System.out.println(c);
}

字符串比较

java
String str1 = "Hello";
String str2 = "Hello";

System.out.println(str1 == str2); // true

String str3 = new String("Hello");
String str4 = new String("Hello");

System.out.println(str3 == str4); // false
System.out.println(str3.equals(str4)); // true
java
String str1 = "Hello";

String str2 = "hello";

System.out.println(str1.equals(str2)); // false

System.out.println(str1.equalsIgnoreCase(str2)); // true
java
String str1 = "abc";

String str2 = "a" + "b" + "c";  // 编译时优化 "a" + "b" + "c" 会被优化为 "abc"

System.out.println(str1 == str2); // true

字符串截取

java
String str1 = "Hello";

System.out.println(str1.substring(0, 1)); // H

字符串替换

java
String str1 = "Hello";

System.out.println(str1.replace("H", "W")); // Output: Wello

字符是否包含

java
String str1 = "Hello";

System.out.println(str1.contains("H")); // true

字符串拼接

java
String str1 = "Hello";

str1 += " World";

System.out.println(str1); // Hello World

Static关键字

静态变量

静态变量是属于类的,而不是属于对象的。静态变量在类加载时初始化,不需要创建对象。可以被类的所有对象共享。

java
public class Main {
    public static void main(String[] args) {

        User user1 = new User("John");
        User user2 = new User("Jane");
        User user3 = new User("Doe");

        System.out.println(User.count); // 3

    }
}

class User {
    static int count = 0;
    private String name;

    public User(String name) {
        this.name = name;
        count++;
    }

    public User() {
        count++;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

静态方法

静态方法是属于类的,而不是属于对象的。静态方法在类加载时初始化,不需要创建对象。可以直接通过类名调用。

java
public class Main {
    public static void main(String[] args) {
        System.out.println(User.getCount()); // 0
        
        User user1 = new User("John");
        User user2 = new User("Jane");
        User user3 = new User("Doe");

        System.out.println(User.getCount()); // 3

    }
}

class User {
    private static int count = 0;
    private String name;

    public User(String name) {
        this.name = name;
        count++;
    }

    public User() {
        count++;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public static int getCount() {
        return count;
    }
}

代码块

代码块是类的五大成员之一 (成员变量、方法、构造器、代码块、内部类)。

静态代码块

  • 格式:static {}
  • 特点:随着类的加载而执行,只执行一次。
  • 作用:用来给类的静态变量赋值。
java
public class Main {
    public static void main(String[] args) {
        System.out.println(User.getCount()); // 0
        
        User user1 = new User("John");
        User user2 = new User("Jane");
        User user3 = new User("Doe");

        System.out.println(User.getCount()); // 3

    }
}

class User {
    private static int count;
    private String name;

    static {
        count = 0;
    }

    public User(String name) {
        this.name = name;
        count++;
    }

    public User() {
        count++;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public static int getCount() {
        return count;
    }
}

非静态代码块 (实例代码块)

  • 格式:{}
  • 特点:每创建一个对象就执行一次,优先于构造器执行。
  • 作用:用来给对象的成员变量赋值。
java
public class Main {
    public static void main(String[] args) {
        User user1 = new User("John");
        User user2 = new User("Jane");
        User user3 = new User("Doe");

    }
}

class User {
    private static int count;
    private String name;

    static {
        count = 0;
    }

    {
        System.out.println("非静态代码块执行");
    }

    public User(String name) {
        System.out.println("构造器执行");
        this.name = name;
        count++;
    }

    public User() {
        count++;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public static int getCount() {
        return count;
    }
}

单例模式

单例模式是一种创建型设计模式,保证一个类只有一个实例,并提供一个全局访问点。

应用场景:线程池、数据库连接池、日志对象、共享的配置对象等。

饿汉式(提前创建实例)

java
public class Main {
    public static void main(String[] args) {
        A a = A.getInstance();
        A b = A.getInstance();
        System.out.println(a == b);

    }
}

 class A {
    private static final A instance = new A();

    private A() {
    }
    
    public void print() {
        System.out.println("Hello");
    }

    public static A getInstance() {
        return instance;
    }
}

懒汉式(延迟创建实例)

java
public class Main {
    public static void main(String[] args) {

        var b1 = B.getInstance();
        var b2 = B.getInstance();

        System.out.println(b1 == b2); // true
    }
}

class B {
    private static B instance;

    private B() {
    }

    public void print() {
        System.out.println("Hello");
    }

    public static B getInstance() {
        if (instance == null) {
            instance = new B();
        }
        return instance;
    }
}

继承

继承是面向对象的三大特性之一,用来描述类与类之间的关系。

继承的特点

  • 子类可以继承父类的非私有成员(成员变量、方法、构造器、代码块、内部类)。
  • Java中只支持单继承,一个类只能有一个父类。
  • Java中支持多层继承,一个类可以有多个子类。
  • Java中所有类都直接或间接继承自Object类。

权限修饰符

  • private:只能在本类中访问。
  • 缺省:不写,只能在同一个包中的类中访问。
  • protected:本类、同一个包中的类、子孙类中可以访问。(子类中用父类访问是不行的)
  • public:任何地方都可以访问。
修饰符本类同一个包中的类子孙类任意类
private×××
缺省××
protected×
public
java
public class Main {
    public static void main(String[] args) {
            Fu fu = new Fu();

            Zi zi = new Zi();

            zi.publicMethod();

    }
}

class Fu {

    private void privateMethod() {
        System.out.println("-----------privateMethod-----------");
    }

    void defaultMethod() {
        System.out.println("-----------defaultMethod-----------");
    }

    protected void protectedMethod() {
        System.out.println("-----------protectedMethod-----------");
    }

    public void publicMethod() {
        System.out.println("-----------publicMethod-----------");
    }
}

class Zi extends Fu {
    public void test() {
        //  privateMethod(); // error
        defaultMethod();
        protectedMethod();
        publicMethod();
    }
}

方法重写

方法重写是指子类中可以根据需要对从父类继承来的方法进行重新编写。

  • 子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限(public > protected > 缺省 )
  • 重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。
  • 私有方法、静态方法不能被重写,如果重写会报错的。
java
public class Main {
    public static void main(String[] args) {
        Fu f = new Fu();
        f.show("hello");
        Zi z = new Zi();
        z.show("hello");
    }
}

 class Fu {
    public void show(String str) {
        System.out.println("Fu show " + str);
    }
}

class Zi extends Fu {
    @Override
    public void show(String str) {
        System.out.println("Zi show " + str);
    }
}

super关键字

super关键字是一个引用变量,用来访问父类的成员。

  • super.成员变量:访问父类的成员变量。
  • super.成员方法:访问父类的成员方法。
  • super():访问父类的构造器。
java
public class Main {
    public static void main(String[] args) {
        Fu f = new Fu("李雷");
        f.show("hello");
        System.out.println(f.name);
        Zi z = new Zi( "李敏");
        z.show("hello");
        System.out.println(z.name);
    }
}

 class Fu {
    String name ;
    Fu(String name) {
        this.name = name;
    }
    public void show(String str) {
        System.out.println("Fu show " + str);
    }
}

class Zi extends Fu {
    Zi(String name) {
        super(name);
    }

    @Override
    public void show(String str) {
        System.out.println("Zi show " + str);
    }
}

this调用构造器

java
public class Main {
    public static void main(String[] args) {
        Zi z = new Zi();
    }
}

class Fu {
    Fu() {
        System.out.println("Fu constructor");
    }
}

class Zi extends Fu {
    Zi() {
        this(10);
        System.out.println("Zi constructor");
    }

    Zi(int i) {
        System.out.println("Zi constructor with parameter");
    }
}

多态

多态的概念

多态是面向对象的三大特性之一,指一个引用变量在不同情况下所表现出来的多种形态。

  • 多态的前提:继承/实现关系、存在方法重写、父类引用指向子类对象。
  • 多态的好处:提高了程序的扩展性。
  • 多态的弊端:不能使用子类特有的方法。(可以通过向下转型解决)
java
package org.example;

public class Main {
    public static void main(String[] args) {
        // 对象的多态性
        Animal dog = new Dog();
        Animal cat = new Cat();

        // 行为的多态性 编译看左边,运行看右边 前提是方法需要被重写
        dog.run();
        cat.run();

        // 编译报错,因为Animal没有meow方法 Cannot resolve method 'meow' in 'Animal'
        // cat.meow();

        // 如果想调用子类特有的方法,需要向下转型
        Cat c = (Cat) cat;
        c.meow();

        // 属性变量没有多态性 编译看左边,运行还是看左边
        System.out.println(dog.name); // Animal
        System.out.println(cat.name); // Animal

        // 传入的参数是Animal类型,但是实际上是Dog和Cat对象,所以调用的是Dog和Cat的run方法
        System.out.println("Animal run");

        go(dog);
        go(cat);
     }

     static void go(Animal animal) {
        animal.run();
    }
}

class Animal {
    public String name = "Animal";

    public void eat() {
        System.out.println("Animal is eating");
    }

    public void run() {
        System.out.println("Animal is running");
    }
}

class Dog extends Animal {
    public String name = "Dog";

    public void bark() {
        System.out.println("Dog is barking");
    }

    @Override
    public void run() {
        System.out.println("Dog is running");
    }
}

class Cat extends Animal {
    public String name = "Cat";

    public void meow() {
        System.out.println("Cat is meowing");
    }

    @Override
    public void run() {
        System.out.println("Cat is running");
    }
}

多态的好处

  • 在多态形式下,右边对象是解耦合的,更便于扩展和维护。
  • 定义方法时,使用父类类型的形参,可以接收一切子类对象,扩展性更强、更便利。

多态下的类型转换

  • 自动类型转换:父类引用指向子类对象,可以直接赋值。 Animal dog = new Dog();
  • 强制类型转换:父类引用指向子类对象,需要强制类型转换。 Animal cat = new Cat(); Cat c = (Cat) cat;

强制类型转换时,需要注意类型转换异常:ClassCastException

java
public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog();
        Animal cat = new Cat();

        // 向下转型
        Cat c = (Cat) cat;
        c.meow();

        // 向下转型异常 ClassCastException
        Dog d = (Dog) cat;
        d.bark();
    }
}

解决方法:使用instanceof关键字判断对象的类型

java
public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog();
        Animal cat = new Cat();

        if (cat instanceof Cat) {
            Cat c = (Cat) cat;
            c.meow();
        }

        if (dog instanceof Dog) {
            Dog d = (Dog) dog;
            d.bark();
        }
    }
}

final关键字

final关键字是一个修饰符,可以修饰类、方法、变量。

  • final修饰的类不能被继承。
  • final修饰的方法不能被重写。
  • final修饰的变量是常量,只能赋值一次。

final修饰类

java
public final class Dog {
    public void bark() {
        System.out.println("Dog is barking");
    }
}

class Husky extends Dog {
    // error: cannot inherit from final Dog
}

final修饰方法

java
public class Dog {
    public final void bark() {
        System.out.println("Dog is barking");
    }
}

class Husky extends Dog {
    // error: overridden method is final
    public void bark() {
        System.out.println("Husky is barking");
    }
}

final修饰变量

java
public class Main {
    public static void main(String[] args) {
        final int a = 10;
        // error: cannot assign a value to final variable a
        a = 20;
    }
}

final修饰引用变量

java
public class Main {
    public static void main(String[] args) {
        final Dog dog = new Dog();
        dog.bark();

        // error: cannot assign a value to final variable dog
        dog = new Dog();
    }
}

class Dog {
    public void bark() {
        System.out.println("Dog is barking");
    }
}

final修饰类变量

java
public class Main {
    public static void main(String[] args) {
        System.out.println(Dog.NUMBER);
    }
}

class Dog {
    public static final int NUMBER;

    static {
        NUMBER = 10;
    }

    void setNumber(int number) {
        // Error: cannot assign a value to final variable NUMBER
        NUMBER = number;
    }
}

常量

常量是指在程序运行过程中,值不会发生改变的量。

  • 使用了static和final修饰的变量,称为常量。

好处

  • 提高程序的可维护性。
  • 程序编译后,常量会被"宏替换",提高程序的运行效率。
java
public class Main {
    public static void main(String[] args) {
        System.out.println(Dog.NUMBER);
    }
}

class Dog {
    public static final int NUMBER = 10;
}

验证

编译后直接查看class文件,常量会被替换为具体的值。

java
public class Main {
    public static void main(String[] args) {
        System.out.println(10);
    }
}

枚举

枚举是一种特殊的类,用来表示固定个数的常量。

java
public class Main {
    public static void main(String[] args) {
        System.out.println(Season.SPRING); // SPRING
        System.out.println(Season.SUMMER); // SUMMER
        System.out.println(Season.AUTUMN); // AUTUMN
        System.out.println(Season.WINTER); // WINTER
    }
}

enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

枚举的属性和方法

java
public class Main {
    public static void main(String[] args) {
        System.out.println(Season.SPRING); // SPRING
        System.out.println(Season.SUMMER); // SUMMER
        System.out.println(Season.AUTUMN); // AUTUMN
        System.out.println(Season.WINTER); // WINTER

        System.out.println(Season.SPRING.getName()); // Spring
        System.out.println(Season.SUMMER.getName()); // Summer
        System.out.println(Season.AUTUMN.getName()); // Autumn
        System.out.println(Season.WINTER.getName()); // Winter
    }
}

public enum Season {
    SPRING("Spring"), SUMMER("Summer"), AUTUMN("Autumn"), WINTER("Winter");

    private final String name;

    Season(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
java
public enum Color {
    RED(255, 0, 0),
    GREEN(0, 255, 0),
    BLUE(0, 0, 255);

    private final int r;
    private final int g;
    private final int b;

    Color(int r, int g, int b) {
        this.r = r;
        this.g = g;
        this.b = b;
    }

    public int getR() { return r; }
    public int getG() { return g; }
    public int getB() { return b; }
}

抽象类

在Java中有一个关键字叫:abstract,它就是抽象的意思,可以用它修饰类、成员方法。

abstract修饰类,这个类就是抽象类;修饰方法,这个方法就是抽象方法。

抽象类最主要的特点:抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现。

一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。

父类知道每个子类都要做某个行为,但每个子类要做的情况不一样,父类就定义成抽象方法,交给子类去重写实现,我们设计这样的抽象类,就是为了更好的支持多态。

java
package org.example;

public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog();
        dog.run();

        Animal cat = new Cat();
        cat.setName("Tom");
        cat.run();
        System.out.println(cat.getName());
    }
}

abstract class  Animal {
    private String name;
    public abstract void run();

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

class Dog extends  Animal {
    @Override
    public void run() {
        System.out.println("Dog is running");
    }
}

class Cat extends  Animal {
    @Override
    public void run() {
        System.out.println("Cat is running");
    }
}

抽象类,模板方法设计模式

解决方法中存在重复代码的问题

java
package org.example;

public class Main {
    public static void main(String[] args) {
        Person student = new Student();
        student.write();

        Person teacher = new Teacher();
        teacher.write();
    }
}

abstract class Person {

    public final void write() {
        System.out.println("标题:繁星之下");

        content();

        System.out.println("结尾:敬上");
    }

    public abstract void content();
}

class Student extends Person {
    @Override
    public void content() {
        System.out.println("正文:在繁星之下,我看到了你");
    }
}

class Teacher extends Person {
    @Override
    public void content() {
        System.out.println("正文:在繁星之下,我看到了我自己");
    }
}

接口

接口中的方法默认是public abstract的。

接口中的变量默认是public static final的。

可以同时实现多个接口 class A implements B,C

java
package org.example;

public class Main {
    public static void main(String[] args) {
        Person student = new Student();
        student.write();

        Person teacher = new Teacher();
        teacher.write();

        System.out.println(Person.name);
    }
}

interface Person {
    String name = "Person";
    void write();
}

class Student implements Person {
    @Override
    public void write() {
        System.out.println("学生写作业");
    }
}

class Teacher implements Person {
    @Override
    public void write() {
        System.out.println("老师批改作业");
    }
}

接口之间多继承

java
package org.example;

interface A {
    void testA();
}

interface B {
    void testB();
}

interface C extends A, B {
    void testC();
}

class D implements C {
    @Override
    public void testA() {
        System.out.println("testA");
    }

    @Override
    public void testB() {
        System.out.println("testB");
    }

    @Override
    public void testC() {
        System.out.println("testC");
    }
}

public class Main {
    public static void main(String[] args) {
        D d = new D();
        d.testA();
        d.testB();
        d.testC();
    }
}

接口的三种方法

java
package org.example;

interface A {

    default void test() {
        System.out.println("test");  // 默认方法 Java 8
        test3();
    }

    static void test2() {
        System.out.println("test2"); // 静态方法 Java 8
    }

    private void test3() {
        System.out.println("test3");  // 私有方法 不需要实现 Java 9
    }

    void say();
}

class B implements A {

    @Override
    public void test() {
        System.out.println("test B");
    }

    @Override
    public void say() {
        System.out.println("say");
    }
}

public class Main {
    public static void main(String[] args) {
        B b = new B();
        b.test();
        A.test2();
    }
}

接口、类、继承关系

  • 一个类可以实现多个接口。
  • 一个接口可以继承多个接口。
  • 一个类可以继承一个类,并实现多个接口。
java
package org.example;

interface A {
    default void test() {
        System.out.println("test A");
    }
}

interface B {
    default void test() {
        System.out.println("test B");
    }
}

class C {
    public void test() {
        System.out.println("test C");
    }
}

class D extends C implements A, B {
    @Override
    public void test() {
        System.out.println("test D"); // test D
        super.test(); // test C
        B.super.test(); // test B
        A.super.test(); // test A
    }
}

public class Main {
    public static void main(String[] args) {
        D d = new D();
        d.test();
    }
}

内部类


成员内部类

java
package org.example;

public class Main {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.test();

        Outer.Inner inner = outer.new Inner();
        inner.show();
    }
}

class Outer {
    private int num = 10;

    class Inner {
        private int num = 20;

        public void show() {
            int num = 30;
            System.out.println("inner class");
            System.out.println(num); // 30
            System.out.println(this.num); // 20
            System.out.println(Outer.this.num);  // 10
        }
    }

    public void test() {
        System.out.println("outer class");
        Inner inner = new Inner();
        inner.show();
    }
}

静态内部类

java
package org.example;

public class Main {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();
        inner.show();
    }
}

class Outer {
    private static int num = 10;

    public void run() {
        System.out.println("Outer run");
    }

    static class Inner {
        private int num = 20;

        public void show() {
            System.out.println(num);
            System.out.println(Outer.num);

            Outer outer = new Outer();
            outer.run();
        }
    }
}

局部内部内

java
public class Main {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.test();
    }
}

class Outer {
    private int num = 10;

    public void test() {
        // 鸡肋 一般不使用
        class Inner {
            private int num = 20;

            public void show() {
                System.out.println(num);
            }
        }
        
        interface A {}

        Inner inner = new Inner();
        inner.show();
    }
}

匿名内部类

就是一种特殊的局部内部类

特点:匿名内部类本质就是一个子类,并会立即创建出一个子类对象。 作用:用于更方便的创建一个子类对象。

java
package org.example;

abstract class Animal {
    abstract void eat();
}

class Cat extends Animal {
    @Override
    void eat() {
        System.out.println("Cat is eating");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Animal() {
            @Override
            void eat() {
                System.out.println("Eating");
            }
        };
        animal.eat();

        Animal cat = new Cat();
        cat.eat();
    }
}

匿名内部类用法

java
package org.example;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Main {
    public static void main(String[] args) {

        JFrame frame = new JFrame("Hello World");
        JPanel panel = new JPanel();

        JButton button = new JButton("Click me");

        // button action
        // 使用匿名内部类 ActionListener 实现 button 点击事件
//        button.addActionListener(new ActionListener() {
//            @Override
//            public void actionPerformed(ActionEvent e) {
//                System.out.println("Hello World");
//            }
//        });

        button.addActionListener(e -> System.out.println("Hello World"));

        panel.add(button);
        frame.add(panel);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 300);
        frame.setVisible(true);
    }
}

Arrays

Arrays类是Java中的一个工具类,提供了一系列静态方法,用于操作数组。

java
package org.example;

import java.util.Arrays;
import java.util.function.IntUnaryOperator;

public class Main {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 6, 5, 7, 8, 9, 10};

        // 打印数组
        System.out.println(Arrays.toString(arr));

        // 排序
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));

        // 二分查找
        System.out.println(Arrays.binarySearch(arr, 5));

        // 填充
        Arrays.fill(arr, 0);
        System.out.println(Arrays.toString(arr));

        // 比较
        int[] arr2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        System.out.println(Arrays.equals(arr, arr2));

        // 复制
        int[] arr3 = Arrays.copyOf(arr, arr.length);
        System.out.println(Arrays.toString(arr3));

        // 复制指定长度
        int[] arr4 = Arrays.copyOfRange(arr, 0, 5);
        System.out.println(Arrays.toString(arr4));

        // setAll
        Arrays.setAll(arr, i -> i * 2);
        System.out.println(Arrays.toString(arr));

        // 匿名内部类
        Arrays.setAll(arr, new IntUnaryOperator(){
            @Override
            public int applyAsInt(int operand) {
                return operand * 4;
            }
        });
        System.out.println(Arrays.toString(arr));
        
    }
}

Arrays.sort

java
package org.example;

import java.util.Arrays;
import java.util.Comparator;

public class Main {
    public static void main(String[] args) {

        Student[] students = {
                new Student("Aka", 22, 90),
                new Student("Alice", 18, 100),
                new Student("Bob", 20, 70),
                new Student("Aob", 20, 70),
        };

        // Sort by name
        Arrays.sort(students, (s1, s2) -> s1.getName().compareTo(s2.getName()));
        System.out.println(Student.arrayToString(students));

        // Sort by age
        Arrays.sort(students, (s1, s2) -> s1.getAge() - s2.getAge());
        System.out.println(Student.arrayToString(students));

        // 匿名内部类 Sort by score
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                return s1.getScore() - s2.getScore();
            }
        });
        System.out.println(Student.arrayToString(students));

        // 默认排序
        Arrays.sort(students);
        System.out.println(Student.arrayToString(students));
    }
}

class Student implements Comparable<Student> {
    private String name;
    private int age;
    private int score;

    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public int getScore() {
        return score;
    }

    static String arrayToString(Student[] students) {
        StringBuilder sb = new StringBuilder();
        for (Student student : students) {
            // [Alice, 18, 80]
            sb.append(" [").append(student.getName()).append(", ").append(student.getAge()).append(", ").append(student.getScore()).append("] ");
        }
        return sb.toString();
    }

    @Override
    public int compareTo(Student o) {
        // o 为第二个对象
        // 官方规定:返回负数表示当前对象比 o 小 ;返回正数表示当前对象比 o 大,大往后排,小往前排;返回 0 表示相等
        return this.name.compareTo(o.name);
    }
}

Lambda

Lambda表达式是JDK 8开始新增的一种语法形式;作用:用于简化函数式接口匿名内部类的代码写法。

函数式接口: 只有一个抽象方法的接口

java
package org.example;

import java.util.Arrays;
import java.util.Comparator;

public class Main {
    public static void main(String[] args) {

        Student[] students = {
                new Student("Aka", 22, 90),
                new Student("Alice", 18, 100),
                new Student("Bob", 20, 70),
                new Student("Aob", 20, 70),
        };

        // Sort by name
        Arrays.sort(students, (s1, s2) -> s1.getName().compareTo(s2.getName()));
        System.out.println(Student.arrayToString(students));

        // Sort by age
        Arrays.sort(students, (s1, s2) -> s1.getAge() - s2.getAge());
        System.out.println(Student.arrayToString(students));

        // 匿名内部类 Sort by score
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                return s1.getScore() - s2.getScore();
            }
        });
        System.out.println(Student.arrayToString(students));

        // 默认排序
        Arrays.sort(students);
        System.out.println(Student.arrayToString(students));
    }
}

class Student implements Comparable<Student> {
    private String name;
    private int age;
    private int score;

    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public int getScore() {
        return score;
    }

    static String arrayToString(Student[] students) {
        StringBuilder sb = new StringBuilder();
        for (Student student : students) {
            // [Alice, 18, 80]
            sb.append(" [").append(student.getName()).append(", ").append(student.getAge()).append(", ").append(student.getScore()).append("] ");
        }
        return sb.toString();
    }

    @Override
    public int compareTo(Student o) {
        // o 为第二个对象
        // 官方规定:返回负数表示当前对象比 o 小 ;返回正数表示当前对象比 o 大,大往后排,小往前排;返回 0 表示相等
        return this.name.compareTo(o.name);
    }
}

方法引用

方法引用是一种函数式接口的实现方式,可以简化Lambda表达式。

  • 方法引用是Lambda表达式的一种简写形式。
  • 方法引用的前提是Lambda表达式中只有一行代码。
java
package org.example;

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {

        Student[] students = {
                new Student("Aka", 22, 90),
                new Student("Alice", 18, 100),
                new Student("Bob", 20, 70),
                new Student("Aob", 20, 70),
        };

        // Sort by name
        Arrays.sort(students, (s1, s2) -> s1.getName().compareTo(s2.getName()));
        System.out.println(Student.arrayToString(students));

        // Sort by age
        Arrays.sort(students, (s1, s2) -> s1.getAge() - s2.getAge());
        System.out.println(Student.arrayToString(students));

//        // 匿名内部类 Sort by score
//        Arrays.sort(students, new Comparator<Student>() {
//            @Override
//            public int compare(Student s1, Student s2) {
//                return s1.getScore() - s2.getScore();
//            }
//        });
//        System.out.println(Student.arrayToString(students));

        // 1. 静态方法引用 Sort by score
        Arrays.sort(students, Student::compareByScore);
        System.out.println(Student.arrayToString(students));

        // 2. 实例方法引用 Sort by age
        Student s = new Student("Aka", 22, 90);

        Arrays.sort(students, s::compareByAge);
        System.out.println(Student.arrayToString(students));

        // 默认排序
        Arrays.sort(students);
        System.out.println(Student.arrayToString(students));
    }
}

class Student implements Comparable<Student> {
    private String name;
    private int age;
    private int score;

    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public int getScore() {
        return score;
    }

    static String arrayToString(Student[] students) {
        StringBuilder sb = new StringBuilder();
        for (Student student : students) {
            // [Alice, 18, 80]
            sb.append(" [").append(student.getName()).append(", ").append(student.getAge()).append(", ").append(student.getScore()).append("] ");
        }
        return sb.toString();
    }

    @Override
    public int compareTo(Student o) {
        // o 为第二个对象
        // 官方规定:返回负数表示当前对象比 o 小 ;返回正数表示当前对象比 o 大,大往后排,小往前排;返回 0 表示相等
        return this.name.compareTo(o.name);
    }

    static int compareByScore(Student s1, Student s2) {
        return s1.getScore() - s2.getScore();
    }

    public int compareByAge(Student s1, Student s2) {
        return s1.getAge() - s2.getAge();
    }
}

特定类型的方法引用

java
package org.example;

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {

        String[] names = {"John", "Jane", "Adam", "Tom", "Jerry","ada","jbk"};

        {
            String[] copy = Arrays.copyOf(names, names.length);
            // Sort the array By name string
            Arrays.sort(copy);
            System.out.println("Sorted names: " + Arrays.toString(copy));
        }

        {
            String[] copy = Arrays.copyOf(names, names.length);
            // Sort the array By name ignoring case
            Arrays.sort(copy, String.CASE_INSENSITIVE_ORDER);
            System.out.println("Sorted names ignoring case: " + Arrays.toString(copy));
        }

        {
            String[] copy = Arrays.copyOf(names, names.length);
            // Sort the array By name ignoring case
            Arrays.sort(copy, (a, b) -> a.compareToIgnoreCase(b));
            System.out.println("Sorted names ignoring case: " + Arrays.toString(copy));
        }

        {
            String[] copy = Arrays.copyOf(names, names.length);
            // Sort the array By name ignoring case
            Arrays.sort(copy, String::compareToIgnoreCase);
            System.out.println("Sorted names ignoring case: " + Arrays.toString(copy));
        }
    }
}

构造器引用

java
package org.example;

public class Main {
    public static void main(String[] args) {

        CreateCar Ccar = new CreateCar() {
            @Override
            public Car create(String name) {
                return new Car(name);
            }
        };

        CreateCar Ccar1 = (name) -> new Car(name);

        // 构造器引用
        CreateCar Ccar2 = Car::new;
    }
}

@FunctionalInterface
interface CreateCar {
    Car create(String name);
}

class Car {
    private String name;

    Car(String name){
        this.name = name;
    }
}
Copyright © RyChen 2024