JavaStudy

JavaBasic

  • 创建的文件名需与类名一致,即HelloWorld.java,严格要求大小写。
  • 主函数参数可为String args[]String[] args
  • 一个源文件只能有一个public类,且仅为文件名相同的类为public属性。
  • java文件运行是javacHello.java文件编译成Hello.class的字节码,然后由jvm虚拟机对其进行解释执行。
public class HelloWorld{
	public static void main(String[] args){
		System.out.println("Hello World")
	}
}

访问控制符

  • privatedefaultprotectedpublic四个标识符。
    | | 同一个类中 | 同一个包中 | (不同包)子类中 | 全局范围内 |
    | --- | --- | --- | --- | --- |
    | private | ✓ | | | |
    | default | ✓ | ✓ | | |
    | protected | ✓ | ✓ | ✓ | |
    | public | ✓ | ✓ | ✓ | ✓ |

private

private只允许当前类进行访问,继承也无法访问。

public class AccessControlStudy {
    private int age = 18;
    public String name = "Pan3a";
    protected String love = "java";

    private void sayAge(){
        System.out.println("age:" + Integer.toString(this.age) );
    }

    public void sayName(){
        System.out.println("name:" + this.name);
    }

    protected void sayLove(){
        System.out.println("love:" + this.love);
    }
}

class Test extends AccessControlStudy{

}

class PrivateStudy{
    public static void main(String[] args) {
        AccessControlStudy ac = new AccessControlStudy();
        Test test = new Test();
//        ac.sayAge();    
//        test.sayAge();  
//       因为private原因,直接无法编译。子类和实例化对象都无法访问。
        ac.sayName();
        test.sayName();
        ac.sayLove();
        test.sayLove();
    }
}

default

  • 只能是同一个类或同一个包中访问。
package com.Pan3a.DefaultStudy;
public class AccessControlStudy{
    String name = "Pan3a";
}
  • 不同的另外一个包
package com.Pan3a.Class;
public class AccessControlStudyThree {
    String name = "Pan3a";

    public  void SayName(){
        System.out.println("Hello " + this.name);
    }
}
  • 测试文件
package com.Pan3a.DefaultStudy;

import com.Pan3a.Class.AccessControlStudyThree;

public class AccessControlStudyTwo {
    public static void main(String[] args) {
//      同一个包中的default可以使用
        com.Pan3a.DefaultStudy.AccessControlStudy ac = new com.Pan3a.DefaultStudy.AccessControlStudy();
        System.out.println(ac.name);

//      不同包中
        com.Pan3a.Class.AccessControlStudyThree three = new AccessControlStudyThree();
//      System.out.println(three.name);
//      因为在不用包中因此调用时语法错误无法编译

//      因为访问的是AccessControlStudyThree中的SayName方法,变量是实例化的类中因此可访问
        three.SayName();
    }

}

protected

  • 同一个类或同一个包或不同包中子类访问。
package com.Pan3a.DefaultStudy;
public class AccessControlStudy{
    protected String name = "Pan3a";
}
  • 不同包中
package com.Pan3a.Class;
public class AccessControlStudyThree {
    protected String name = "Pan3a";

    public  void SayName(){
        System.out.println("Hello " + this.name);
    }
}
  • protected属性访问用继承式。
package com.Pan3a.DefaultStudy;

import com.Pan3a.Class.AccessControlStudyThree;

class ProtectedStudy extends AccessControlStudyThree{
    ProtectedStudy(){
        System.out.println("Hello " + super.name);
    }
}

public class AccessControlStudyTwo {
    public static void main(String[] args) {
//      同一个包中的default可以使用
        com.Pan3a.DefaultStudy.AccessControlStudy ac = new com.Pan3a.DefaultStudy.AccessControlStudy();
        System.out.println(ac.name);

//      不同包中
        com.Pan3a.Class.AccessControlStudyThree three = new AccessControlStudyThree();
//        System.out.println(three.name);
//      因为在不用包中因此调用时语法错误无法编译

//      虽然是不同包中,但是这里可以通过继承的来访问
        ProtectedStudy protectedStudy = new ProtectedStudy();

//      因为访问的是AccessControlStudyThree中的SayName方法,变量是实例化的类中因此可访问
        three.SayName();
    }
}

public

  • 适用于任何情况,但实际项目仍需手动指定属性。

字符 && 字符串

  • 字符用'P'这样的单引号进行包裹。
  • 字符串用"Hello World"这样的双引号进行包裹。

字符数组

  • 字符数组
public class CharStudy{}   
	public	static void main(String[] args){
        char[] HelloArray = {'H','e','l','l','o'};
            String HelloString = new String(HelloArray);
            System.out.println(HelloString);
            System.out.println(HelloString + "字符长度为:" + HelloArray.length);
    }
}

创建字符串

public class StringStudy{
    public static void main(String[] args){
        // 会创建一个匿名对象
        String stringOne = "Hello";
        System.out.println(stringOne);
        
        // 构造函数创建字符串
        String stringTwo = new String("Pan3a");
        System.out.println(stringTwo);
        
        // 字符串拼接
        String stringThree = "Hello " + stringTwo;
        System.out.println(stringThree);
        
        // 字符对比
        String stringFour = stringOne.concat(stringTwo);
        String stringFive = stringOne + stringTwo;
        String stringSix = "Hello Pan3a";
        // 这里的 == 是比较内存中存放的首地址  equals 则是比较字符是否相同
        if(stringSix == stringFour){
            System.out.println("OK");
        }if(stringSix.equals(stringFour)){
            System.out.println("OK2");
        }
    }
}

格式化字符串

  • 格式化数字可以用printf()format()方法。
  • format()返回一个String对象而不是PrintStream,可以创建一个可复用的格式化字符串。
public class StringStudy{
    public static void main(String[] args){
                int intVar = 1;
        String stringVar = "Hello World";
        System.out.printf("整型变量:" + "%d" + " 字符串变量:%s" + "\n",intVar,stringVar);

        String fs;
        fs = String.format("整型变量:" + "%d" + " 字符串变量:%s",intVar,stringVar);
        System.out.println(fs);
    }
}

StringBuffer && StringBuilder

  • 这里的StringBufferStringBuilder来由是因为平常创建的字符串在修改的时候是重新创建的一个对象,而不是原字符串。后者没有线程安全,但是相比前者后者有速度优势,因此大多数情况下建议使用后者。
public class StringStudy{
    public static void main(String[] args){
        StringBuilder sb = new StringBuilder(10);
        sb.append("Hello World");
        System.out.println(sb);
        for(int num=0;num<sb.length();num++){
            System.out.println(sb.charAt(num));
        }
        // 这里实例化类会将字符进行一次输出
        StringBuffer sBuffer = new StringBuffer("Hello Pan3a");
        sBuffer.append("你好,");
        sBuffer.append("Pan3a");
        System.out.println(sBuffer);
    }
}

数组

  • 数组的遍历
public class ArrayStudy {
    public static void main(String[] args) {
//        数组大小
        int size = 10;
        int[] myList = new int[size];
        for (int num=0;num<size;num++){
            myList[num] = size-(num+1);
            System.out.println(Integer.toString(num) + " " + myList[num]);
        }

//        加强型循环
        for (int value:myList){
            System.out.println(value);
        }
    }
}

日期时间

  • 有时候需要查看当前时间并且格式化输出。
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateStudy {
    public static void main(String[] args) {
        Date date = new Date();
        SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

        System.out.println(date.getTime());
        System.out.println(date.toString());

        System.out.println("当前时间:" + ft.format(date));
        System.out.printf("年-月-日:%tF%n",date);
    }
}

正则表达式

  • 正则处理文本。
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ReStudy {
    public static void main(String[] args) {
        String info = "My name is Pan3a,I am from China";
        String pattern = ".*Pan3a.*";

        boolean isMatch = Pattern.matches(pattern,info);
        System.out.println("字符是否包含 'Pan3a' ?" + isMatch);
    }
}

I/O

  • 平常接触多的应该就算文件的操作了。

File

  • 创建文件有个临时文件,删除文件
import java.io.*;

public class FileStudy{
    public static void main(String[] args) throws IOException{
        String filePath = "C:\CodeProject\JavaStudy\src\Flag";
        File file = new File(filePath);
        System.out.println(file);
//      返回构造方法传入的路径
//        System.out.println(file.getPath());
//      返回绝对路径
//        System.out.println(file.getAbsolutePath());
//      类似于绝对路径,但是更规范
//        System.out.println(file.getCanonicalPath());
        if(file.isFile()){
            System.out.println(file.getAbsoluteFile() + " 这是一个文件");
//          判断文件是否可读
            if(file.canRead()){
                System.out.println(file.getAbsoluteFile() + " 文件可读");
            }else {
                System.out.println(file.getAbsoluteFile() + " 文件不可读");
            }
//          判断文件是否可写
            if (file.canWrite()){
                System.out.println(file.getAbsoluteFile() + " 文件可写");
            }
//          判断文件可执行
            if(file.canExecute()){
                System.out.println(file.getAbsoluteFile() + " 文件可执行");
            }
        }
      File tempFile = File.createTempFile("tmp",".txt");
      if(tempFile.isFile()){
     	 System.out.println(tempFile.getAbsoluteFile() + " 临时文件创建成功");
		 tempFile.deleteOnExit();
 	     System.out.println(tempFile.getAbsolutePath());
      }
    }
}

目录

  • 和文件类似,多的是目录中的文件和目录遍历,目录删除时无法删除非空目录。
import java.io.*;

public class FileStudy{
    public static void main(String[] args) throws IOException{
        //      创建目录
       File createDir = new File("Hello");
       // File createDirs = new File("Hello/Hello/Hello"); 
       // if(createDirs.mkdirs())   这里mkdirs 可以创建没有的父目录
       if(createDir.mkdir()){
           System.out.println("OK");
           if(createDir.delete()){
               // 这里的删除只能删除非空的目录
               System.out.println(createDir.getAbsolutePath() + " 文件删除成功");
           }
       }
       String dirPath = "C:\\windows";
       File dir = new File(dirPath);
       File[] dirs = dir.listFiles(new FilenameFilter() {
            // 重载方法,过滤不需要的文件
            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(".exe");
            }
       }
  	   );
//        for (int i=0;i<dirs.length;i++){
//            System.out.println(dirs[i]);
//        }
        for (File f:dirs){
            System.out.println(f);
        }
    }
}

InputStream

  • 所有与IO操作相关的代码都必须正确处理IOException,否则无法正常运行。
  • 读取文本是字节或字符串。
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class InputStreamStudy {
    public static void readFile() throws IOException{
        try(InputStream inputStream = new FileInputStream("c://CodeProject//JavaStudy//src//Flag")){
            int n;
            while ((n = inputStream.read()) != -1){
                System.out.println((char) n);
            }
        }
    }

    public static void readFileBuffer() throws IOException{
        try(InputStream inputStream = new FileInputStream("c://CodeProject//JavaStudy//src//Flag")){
            byte[] buffer = new byte[1000];
            int n;
            while ((n = inputStream.read(buffer)) != -1){
                System.out.println("read " + n + " bytes");
            }
        }
    }

    public static String readFileAsString(InputStream inputStream) throws IOException{
        int n;
        StringBuilder stringBuilder = new StringBuilder();
        while ((n = inputStream.read()) != -1){
            stringBuilder.append((char) n);
        }
        return stringBuilder.toString();
    }

    public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("c://CodeProject//JavaStudy//src//Flag");
        for (;;){
            int n = inputStream.read();  // 反复读取
            if(n == -1){
                break;
            }
            System.out.println(n); // 打印的byte的值
        }
        inputStream.close();

//        如果代码出错,并不会回收输入流,可用try
        readFile();

//        一次读取一个字节不高效,因此可以使用缓冲
        readFileBuffer();

//        读取文本字符
        String string;
        try(InputStream input = new FileInputStream("c://CodeProject//JavaStudy//src//Flag")){
            string = readFileAsString(input);
        }
        System.out.println(string);

    }
}

OutputStream

  • 文件写入,没看到追加
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class OutputStreamStudy {

    public static void main(String[] args) throws IOException{
        String fileName = "c:\\CodeProject\\JavaStudy\\src\\Flag";
        try(OutputStream outputStream = new FileOutputStream("c:\\CodeProject\\JavaStudy\\src\\Flag")){
            outputStream.write("Hello Pan3a".getBytes("UTF-8"));
        }
    }
}

Scanner

  • 推荐hasNextLine方法,直接获取全部数据,hasNext无法获取空格,认为其是结束符。
import java.util.Scanner;

public class ScannerStudy {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("next方法接收:");
//      判断是否还有输入
        if(scanner.hasNext()){
            String stringOne = scanner.next();
            System.out.println("输入的数据为:" + stringOne);
        }
        scanner.close();

        Scanner scan = new Scanner(System.in);
        System.out.print("nextLine方式接收:");
        if(scan.hasNextLine()){
            String stringTwo = scan.nextLine();
            System.out.println("输入的数据为:" + stringTwo);
        }
        System.out.print("请输入数字:");
        int count = 0;
        double sum = 0;
        while (scan.hasNextDouble()){
            double number = scan.nextDouble();
            count += 1;
            sum += number;
        }
        System.out.println("一共" + Integer.toString(count) + "个数");
        System.out.println("和为" + sum);
        scan.close();
    }
}

异常处理

面向对象

方法

  • 主要是结合访问控制符和参数传递来实现特定功能。
class Person{
    String[] name = {};

    public Person(String... names){
        for(String name:names){
            System.out.println("构造方法可变参数: " + name);
        }
        this.name = names;
    }

    public void getName(){
        for (String name:this.name) {
            System.out.print(name + "   ");
        }
    }

    public void setName(String[] names){
        for (String setName:names){
            System.out.println("数组类型参数: " + setName);
        }
        this.name = names;
    }
}
public class ObjectFunc {
    public static void main(String[] args) {
        String[] names = {"Pan3a","Forever404"};
//      构造方法实例化
        Person personOne = new Person(names);
//      数组参数
        personOne.setName(names);

//      参数传递 指向的是原变量地址   改变变量实质变量名不变地址为新地址---新对象
        String name = "Pan3a";
        Person personTwo = new Person(name);
        personTwo.getName();
        name = "Forever404";
        personTwo.getName();

//      参数传递 数组地址没改变 改变的是地址中存的值
        String[] color = {"RED","BLUE"};
        Person personThree = new Person(color);
        personThree.getName();
        color[0] = "GREEN";
        System.out.println();
        personThree.getName();
    }
}

构造方法

  • 每个类都有构造方法,没有则Java编译器将会提供一个默认的构造方法。构造方法需与类同名,一个类可以有多个构造方法。
  • 构造方法类似于Python__init__(self)主要作用于类的初始化。
package com.pan3a.test;
public class ObjectConstruct {
    public static void main(String[] args) {
        Person personOne = new Person();
        System.out.println(personOne.getName());
        System.out.println(personOne.getAge());

        Person personTwo = new Person("Pan3a",20);
        System.out.println(personTwo.getName());
        System.out.println(personTwo.getAge());

        Person personThree = new Person("Forever404");
        System.out.println(personThree.getName());
        System.out.println(personThree.getAge());
    }
}

class Person{
    protected String name;
    protected int age;

//  无参数构造方法,会自动创建,默认的构造方法
    public Person(){

    }

//  重载此构造方法,实例化类时根据传递参数自动选择构造方法
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }

//  构造方法调用其他构造方法
    public Person(String name){
        this(name,18);
    }

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

    public int getAge(){
        return this.age;
    }
}

方法重载

  • 方法名相同,参数不同,返回值相同。
  • overload,重载,相当于重新写了一个方法,但是这些方法都不同,因为它们的参数都不一样。
package com.pan3a.hello;
public class ObjectOverload {
    public static void main(String[] args) {
        Person personOne = new Person();
        personOne.hello();
        personOne.hello("Pan3a");
        personOne.hello("Pan3a",16);
        personOne.hello("Pan3a",20);
    }
}

class Person{
    public void hello(){
        System.out.println("Hello World");
    }

    public void hello(String name){
        System.out.println("Hello " + name);
    }

    public void hello(String name,int age){
        if (age > 18){
            System.out.println("Hello " + name + ", you are an adult!");
        }else
            System.out.println("Hello " + name + ", you are a child!");
    }
}

继承

  • 子类无法继承父类的构造方法
  • 子类的构造方法必须与父类的构造方法类型一致   如:无参对应无参
  • 子类的构造方法第一条语句必须是父类构造方法
  • 只能单继承,除Object外没有关键字extends的类都是继承于Object
  • Java15特性,sealedpermits修饰的类只能在指定的类继承
  • Java继承还有向上转型和向下转型两种。
sealed class Color permits Red,Blue,Green{
    
}
package com.pan3a.extend.up;
public class ObjectExtendsUp {
    public static void main(String[] args) {
        //      向上转型 因为继承关系 Student->Person->Object  Student有Person的全部属性
        Person personOne = new Student();
        System.out.println(personOne.name);
        System.out.println(personOne.age);
    }
}

class Person{
    public String name = "Pan3a";
    public int age = 18;
}

class Student extends Person{

}
package com.pan3a.extend.up;
public class ObjectExtendsUp {
    public static void main(String[] args) {
        //        向下转型 也是由于继承关系 但父类无法转为子类 因为子类有父类没有的属性
        Person p1 = new Student();
        Person p2 = new Person();
//        Student s2 = (Student) p2;  这里会由于实例化的Person,但变量类型是Student,变量类型中有Person中没有的属性因此会失败
        if(p1 instanceof Student){
            Student s1 = (Student) p1;
        }
    }
}

class Person{
    public String name = "Pan3a";
    public int age = 18;
}

class Student extends Person{

}
package com.pan3a.extend;
public class ObjectExtends {
    public static void main(String[] args) {
//        Student studentPan3a = new Student("Pan3a",18,60);
        Student studentPan3a = new Student();
        System.out.println(studentPan3a.getAge());
        System.out.println(studentPan3a.getName());
        System.out.println(studentPan3a.getScore());
        studentPan3a.setScore(99);
        System.out.println(studentPan3a.getScore());
    }
}

class Person{
    protected String name;
    protected int age;

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

    public Person() {

    }

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

    public String getName() {
        return name;
    }

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

    public int getAge(){
        return age;
    }
}

class Student extends Person{
    private int score;

    public Student(String name,int age,int score){
//      子类构造方法必须先调用父类构造方法
        super(name,age);
        this.score = score;
    }

//  这里子类的构造方法必须与父类对应  如:无参对应无参
    public Student(){
        super();
    }

    public void setScore(int score){
        this.score = score;
//        System.out.println("Score has change:" + Integer.toString(score));
    }

    public int getScore(){
        return this.score;
    }
}


final class Animal{

}

/*
这里就无法继承Animal类,因为此类用了final关键字进行修饰
class Teacher extends Animal{

}*/

方法重写

  • Overrie,都是同一个方法,类型参数都一样,只不过实现功能有所更改。
package com.pan3a.override;
public class ObjectOverride {
    public static void main(String[] args) {
        Student studentOne = new Student();
        studentOne.hello();
    }
}

class Person{
    public void hello(){
        System.out.println("Hello");
    }
}

class Student extends Person{
    @Override
    public void hello(){
        super.hello();
        System.out.println("Hello World!");
    }
}

多态

  • 根据不同类自动执行不同的方法,动态调用。
package com.pan3a.polymorphism;
public class ObjectPolymorphism {
    public static void running(Person p){
        p.run();
    }

    public static void main(String[] args) {
        running(new Person());
        running(new Student());
    }
}

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

class Student extends Person{
    @Override
    public void run(){
        System.out.println("Student run");
    }
}
  • 具体例子,多态就会自动选择实例类型。
public class ObjectPolymorphismDemo{
    public static void main(String[] args){
//      一个有普通收入 工资收入 国家补贴的人计算税
        Income[] incomes = new Income[]{
                new Income(3000),
                new Salary(7500),
                new StateCouncilSpecialAllowance(15000)
        };
        System.out.println(totalTax(incomes));
    }

    public static double totalTax(Income... incomes){
        double total = 0;
        for (Income income:incomes){
            total += income.getTax();
        }
        return total;
    }
}

class Income{
    protected double income;

    public Income(double income){
        this.income = income;
    }

    public double getTax(){
        return income * 0.1;
    }
}
// 计算税收
class Salary extends Income{
    public Salary(double income){
        super(income);
    }

    @Override
    public double getTax() {
        if (income <= 5000){
            return 0;
        }
        return (income - 5000) * 0.2;
    }
}
// 国家补贴免税收
class StateCouncilSpecialAllowance extends Salary{
    public StateCouncilSpecialAllowance(double income){
        super(income);
    }

    @Override
    public double getTax(){
        return 0;
    }
}

抽象类

  • 抽象类只能被继承,目的是让代码更规范,因为子类必须实现父类定义的方法,即覆写父类方法。
  • 抽象方法,如果一个类中包含抽象方法,不能包含方法体。那么该类必须是抽象类。任何子类必须重写父类抽象方法,除非子类也是抽象类。
package com.pan3a.abstractStudy;
public class AbstractStudy {
    public static void main(String[] args) {
        Person personOne = new Student("pan3a",18);
        personOne.run();
        System.out.println(personOne.getName());
    }
}

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

    public Person(){

    }

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

   public abstract void run();

    public String getName(){
        return name;
    }

}

class Student extends Person{
    private String name;
    private int age;

    public Student(){

    }

//  此处不能使用Override来检查,因为构造房啊不会被继承
    public Student(String name,int age){
        super(name,age);
    }

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

    public void say(){
        System.out.println("Hello " + this.name);
    }

    @Override
    public String getName(){
        String name = super.getName();
        return name;
    }
}

接口

  • 接口也可继承,可一个类实现多个接口
  • 接口可以定义default方法。
  • 接口默认的方法都是public abstract,这两个只是被省略了。
package com.pan3a.interfaceStudy;
public class ObjectInterface {
    public static void main(String[] args) {
        Student personOne = new Student("Pan3a");
        personOne.say();
        personOne.red();
        personOne.medium();
        personOne.printColor();
        System.out.println(personOne.getName());
    }
}

interface Person{
    void say();
    String getName();
}

interface Color{
    void red();
//    定义接口方法,可以直接被继承调用
    default void printColor(){
        System.out.println("this is interface default method");
    }
}
// 接口继承接口
interface Size extends Color{
    void medium();
}

// 一个类实现多个接口
class Student implements Person,Color,Size{
    private String name;

    public Student(String name){
        this.name = name;
    }

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

    @Override
    public String getName(){
        return this.name;
    }

    @Override
    public void red(){
        System.out.println("this is hello method!");
    }

    @Override
    public void medium() {
        System.out.println("this is medium!");
    }
}

内部类

  • 一:直接创建一个类定义在另一个类的内部
  • 这里的访问必须实例化外部类再来请求,内部类可访问父类的私有属性。
package com.pan3a.Inner;
public class ObjectInner {
    public static void main(String[] args) {
        Person personOne = new Person("Pan3a");
        Person.Student student = personOne.new Student();
        student.info();
    }
}

class Person{
    private String name;

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

    class Student{

        void info(){
            System.out.println("Hello " + Person.this.name + " I am a Student!");
        }
    }
}
  • 二:匿名类,不需要在内部定义一个类,直接实例化。
public class ObjectInnerAnonymous {
    public static void main(String[] args) {
        AnonymousDemo anonymousDemo = new AnonymousDemo("Pan3a");
    }
}

class Inner{
    public void display(){
        System.out.println("在 Inner 类内部。");
    }
}

class AnonymousDemo{
    private String name;

    public AnonymousDemo(String name){
        this.name = name;
        inner.display();
    }

    // 匿名类继承一个类
    Inner inner = new Inner(){
        @Override
        public void display(){
            System.out.println("在匿名类内部。");
        }
    };
}
  • 静态内部类

枚举

  • 枚举限制变量只能使用预先设定好的值,相当于常量。如四季的春夏秋冬。
  • 通过name()获取常量定义的字符串,注意不要使用toString(),因为它可以被覆盖。
  • ordinal()获取常量定义的顺序,类似于数组的顺序,但是并没有实质意义,因为更改枚举元素之后顺序会发生变化。
  • enum的构造方法要声明为private,字段强烈建议声明为final,常用于switch语句中。
  • enum中也可以编写构造方法,字段,方法。
  • 常量普通设定方法
class Year{
    public static final String spring = "spring";
    public static final String summer = "summer";
    public static final String autumn = "autumn";
    public static final String winter = "winter";
}
  • 注意Java版本在JDK8版本之前使用equals进行输入对比判断。也可也使用===进行判断。如果使用==比较,它比较的是两个引用类型的变量是否是同一个对象。因此,引用类型比较,要始终使用equals()方法,但enum类型可以例外。
class Year{
    public static final String spring = "spring";
    public static final String summer = "summer";
    public static final String autumn = "autumn";
    public static final String winter = "winter";
}
public class EnumStudy {
    public static void main(String[] args) {
       String day;
       Scanner scan = new Scanner(System.in);
       day = scan.nextLine();
       scan.close();
       if(day.equals(Year.spring) || day.equals(Year.autumn)){
           System.out.println("OK");
       }
    }
}
  • 迭代枚举元素
enum Years{
    SPRING,SUMMER,AUTUMN,WINTER;
}
public class EnumStudy {
    public static void main(String[] args) {
        for (Years y: Years.values()){
            System.out.println(y);
        }
    }
}
  • 结合switch

反射

  • Java的反射,Java的反射是指程序在运行期可以拿到一个对象的所有信息。
  • 创建一个类,后面用来进行测试使用,注意请将一下测试文件都放在一个包内。
package com.pan3a.reflection;

public class ReflectionMain {
}

class Person{
    private int age;
    private String name;
    public long id=9527;
    public long grade;
    protected float score;
    protected int rank;

    public Person(){
    }

    protected Person(long id){
        this(18,"Pan3a",id,9,9999,31);
    }

    private Person(int age){
        this(age,"Pan3a",9527,9,9999,30);
    }

    public Person(int age,String name,long id,long grade,float score,int rank){
        this.age = age;
        this.name = name;
        this.id = id;
        this.grade = grade;
        this.score = score;
        this.rank = rank;
    }

    public int getAge(){
        return age;
    }

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

    public String getName(){
        return name;
    }

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

    public long getId(){
        return id;
    }

    public void setId(long id){
        this.id = id;
    }

    public long getGrade(){
        return grade;
    }

    public void setGrade(long grade){
        this.grade = grade;
    }

    public float getScore(){
        return score;
    }

    public void setScore(float score){
        this.score = score;
    }

    public int getRank(){
        return rank;
    }

    public void setRank(int rank){
        this.rank = rank;
    }

    private static void sayHello(){
        System.out.println("Hello World");
    }

    private void sayHello(String name){
        System.out.println("Hello " + name);
    }

    @Override
    public String toString(){
        final StringBuffer stringBuffer = new StringBuffer("Person{");
        stringBuffer.append("age=").append(age);
        stringBuffer.append(", name='").append(name).append('\'');
        stringBuffer.append(", id=").append(id);
        stringBuffer.append(", grade=").append(grade);
        stringBuffer.append(", score=").append(score);
        stringBuffer.append(", rank=").append(rank);
        stringBuffer.append('}');
        return stringBuffer.toString();
    }
}

class Teacher extends Person{
    private String role = "Teacher";

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

class Student extends Teacher{
    private String role = "Student";

    @Override
    public void sayHello(){
        System.out.println("Hello Student");
    }
}

获取对象

  • 对象的获取有三种方式分别是Class.forName(全类名),对象.getclass()类名.class
  • 这里的三种方式虽然作用都一样,但是都有各自的缺点。
  • class.forName需要知道类名的全路径。对象名.class需要存在已经实例化的对象。类名.class需要提前在编译前知道类名。
  • 下面会发现这里的比较都是true,因此说这里返回的对象都是同一个,因此Person.class只加载了一次。
  • instanceof不但匹配指定类型,还匹配指定类型的子类。而用==判断class实例可以精确地判断数据类型,但不能作子类型比较。
package com.pan3a.reflection;

public class ReflectionGetClass {
    public static void main(String[] args) throws Exception{
        com.pan3a.reflection.Student student = new com.pan3a.reflection.Student();
        com.pan3a.reflection.Teacher teacher = new com.pan3a.reflection.Teacher();
        com.pan3a.reflection.Person person = new com.pan3a.reflection.Person();

        if(student instanceof com.pan3a.reflection.Person){
            System.out.println("Student 是 Person 子类");
        }

//      Class.forName
        Class class1 = Class.forName("com.pan3a.reflection.Person");
        System.out.println("别名:" + class1.getSimpleName());
        System.out.println(class1);

//      类名.class
        Class class2 = com.pan3a.reflection.Person.class;
        System.out.println(class2);

//      对象.getClass()
        com.pan3a.reflection.Person person1 = new com.pan3a.reflection.Person();
        Class class3 = person1.getClass();
        System.out.println(class3);

        System.out.println(class1 == class2);
        System.out.println(class1 == class3);
    }
}

成员变量

  • 获取成员变量需要知道一下四个方法,getFieldgetFieldsgetDeclaredFieldgetDeclaredFields
  • 还可获取成员变量属性的三个方法,getTypegetModifiersgetName。分别是获取变量类型,修饰符,成员名。
  • 他们分别是获取单个成员,和获取所有成员,获取单个成员(忽略修饰服限制,不包括父类),获取多个成员(忽略修饰服限制,不包括父类)。需注意的是使用后面两个是需使用setAccessible(true)来忽略编译时的安全检查。
  • 这里牵扯到了反射实现构造方法,后面也再会讲到。
package com.pan3a.reflection;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class ReflectionGetField {
    public static void main(String[] args) throws Exception{
        Class class1 = Class.forName("com.pan3a.reflection.Person");
        getFieldStudy(class1);
        getFieldsStudy(class1);
        getDeclaredFieldStudy(class1);
        getDeclaredFieldsStudy(class1);
        setFieldStudy(class1);
    }

    public static void getFieldStudy(Class class1) throws Exception{
        System.out.println("getField");
        Field fieldId = class1.getField("id");
        System.out.println(fieldId);
        Field fieldGrade = class1.getField("grade");
        System.out.println(fieldGrade);
        System.out.println();
//      该对象还有其他成员但是用此方法无法获取,因为他们不是用public修饰的
    }

    public static void getFieldsStudy(Class class1){
        System.out.println("getFields");
        Field[] fields = class1.getFields();
        for (Field field : fields){
            System.out.println(field);
        }
        System.out.println();
    }

    public static void getDeclaredFieldStudy(Class class1) throws Exception{
        System.out.println("getDeclaredField");
        Field fieldAge = class1.getDeclaredField("age");
        System.out.println(fieldAge);
        Field fieldName = class1.getDeclaredField("score");
        System.out.println(fieldName);
        System.out.println();
    }

    public static void getDeclaredFieldsStudy(Class class1) throws Exception{
        System.out.println("getDeclaredFields");
        Field[] fields = class1.getDeclaredFields();
        for(Field field:fields){
            System.out.println("成员名:" + field.getName() + "\t成员修饰符:" + field.getModifiers() + "\t成员类型:" + field.getType());
        }
        System.out.println();
    }

//  反射修改私有成员值
    public static void setFieldStudy(Class class1) throws Exception{
        System.out.println("反射获取,修改成员值");
        com.pan3a.reflection.Person person = new com.pan3a.reflection.Person();
        System.out.println("ID:" + person.getId());
//      反射获取成员变量值并且修改成员变量
        Field fieldAge = class1.getDeclaredField("id");
        fieldAge.setAccessible(true);
//      实例化对象为后面获取,修改成员做准备,这里后面还会讲到的构造方法
        Object object = class1.newInstance();
        System.out.println("ID:" + fieldAge.get(object));
        fieldAge.set(object,9999);
        System.out.println("ID:" + fieldAge.get(object));
    }
}

构造方法

  • 平常正向操作都是new一个对象。通过反射调用构造方法有两种方式,分别是Person.class.newInstance()(Person)constructor.newInstance()。两者区别就是前者无法调用含参的构造方法,后者可以。
  • 实例化对象时,对于非public的任然需要constructor.setAccessible(true)
package com.pan3a.reflection;

import java.lang.reflect.Constructor;

public class ReflectionConstructor {
    public static void main(String[] args) throws Exception{
        Class personClass = Class.forName("com.pan3a.reflection.Person");

        System.out.println("所有构造方法");
        Constructor[] constructors = personClass.getDeclaredConstructors();
        for (Constructor constructor:constructors){
            System.out.println(constructor);
        }
        System.out.println();



        System.out.println("public无参数构造方法");
//      默认当前类的无参数构造方法
        Constructor constructor1 = personClass.getConstructor();
        System.out.println(constructor1);

        System.out.println("protected带参数构造方法");
        Constructor constructor2 = personClass.getDeclaredConstructor(long.class);
        System.out.println(constructor2);

        System.out.println("private带参数构造方法");
        Constructor constructor3 = personClass.getDeclaredConstructor(int.class);
        System.out.println(constructor3 + "\n");



        System.out.println("public无参数构造方法创建对象");
        Object person1 = constructor1.newInstance();
        System.out.println(person1);

        System.out.println("protected带参数构造方法创建对象");
        constructor2.setAccessible(true);
        Object person2 = constructor2.newInstance(9528);
        System.out.println(person2);

        System.out.println("private带参数构造方法创建对象");
        constructor3.setAccessible(true);
        Object person3 = constructor3.newInstance(18);
        System.out.println(person3);

        System.out.println("Person.class.newInstance()");
        Class class1 = com.pan3a.reflection.Person.class;
        Object object = class1.newInstance();
        System.out.println(object);
    }
}

成员方法

  • 获取成员方法如通获取成员变量类似,也有四个方法。getMethodgetMethodsgetDeclaredMethodgetDeclaredMethods
  • 获取方法属性,getNamegetReturnTypegetParameterTypesgetModifiers
package com.pan3a.reflection;

import java.lang.reflect.Method;

public class ReflectionMethod {
    public static void main(String[] args) throws Exception{
        Class personClass = Class.forName("com.pan3a.reflection.Person");
        getMethodStudy(personClass);
//        getMethodsStudy(personClass);
        getDeclaredMethodStudy(personClass);
//        getDeclaredMethodsStudy(personClass);
    }

    public static void getMethodStudy(Class personClass) throws Exception{
        System.out.println("getMethod获取单个非public方法");
        Object object = personClass.newInstance();
        Method method = personClass.getMethod("getId");
        System.out.println(method);
        long Id = (long) method.invoke(object);
        System.out.println("Id:" + Id);

//      多态,依旧根据传入的实例化对象为准,如果没有则向父类寻找
        Class teacherClass = Class.forName("com.pan3a.reflection.Teacher");
        Method method1 = teacherClass.getMethod("sayHello");
        method1.invoke(new com.pan3a.reflection.Student());
    }

    public static void getMethodsStudy(Class personClass) throws Exception{
        System.out.println("getMethods获取所有非public方法");
        Method[] methods = personClass.getMethods();
        for (Method method:methods){
            System.out.println(method);
        }
    }

    public static void getDeclaredMethodStudy(Class personClass) throws Exception{
        System.out.println("getDeclaredMethod单个方法不限制修饰符");
        Object object = personClass.newInstance();
        Method method = personClass.getDeclaredMethod("sayHello",String.class);
        System.out.println(method);
        method.setAccessible(true);
        method.invoke(object,"Pan3a");

//      由于这里和方法为静态方法,因此object为null
        Method method1 = personClass.getDeclaredMethod("sayHello");
        method1.setAccessible(true);
        method1.invoke(null);
    }

    public static void getDeclaredMethodsStudy(Class personClass) throws Exception{
        System.out.println("获取所有方法");
        Method[] methods = personClass.getDeclaredMethods();
        for(Method method:methods){
            System.out.println("方法名:" + method.getName() + "\t方法返回值类型:" + method.getReturnType() + "\t方法参数类型:" + method.getParameterTypes() + "\t方法修饰符:" + method.getModifiers());
        }
    }
}

继承关系

  • getSuperclass(),获取父类类型,getInterfaces()获取当前类实现的所有接口。
package com.pan3a.reflection;

public class ReflectionSuper {
    public static void main(String[] args) throws Exception{
        superClass();
        interfaceReflection();
    }

    public static void superClass() throws Exception{
        Class studentClass = Class.forName("com.pan3a.reflection.Student");
        Class teacherClass = studentClass.getSuperclass();
        Class personClass = teacherClass.getSuperclass();
        Class objectClass = personClass.getSuperclass();
        Class objectSuperClass = objectClass.getSuperclass();
        System.out.println(studentClass);
        System.out.println(teacherClass);
        System.out.println(personClass);
        System.out.println(objectClass);
//      综合可看出除了Object类外,如果类没有继承,那么默认继承Object。
        System.out.println(objectSuperClass);
    }

    public static void interfaceReflection() throws Exception{
        Class integer = Integer.class;
        Class[] integerInterfaces = integer.getInterfaces();
        for (Class integerInterface:integerInterfaces){
            System.out.println(integerInterface);
        }
    }
}

动态代理

  • 平常实现接口方式。
package com.pan3a.reflection;

public class ReflectionDynamicProxy {
    public static void main(String[] args) {
        HelloWorld helloWorld = new HelloWorld();
        helloWorld.morning("Pan3a");
    }
}

interface Hello{
    void morning(String name);
}

class HelloWorld implements Hello{
    public void morning(String name){
        System.out.println("Good morning " + name);
    }
}
  • 动态代理实现方法
package com.pan3a.reflection;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ReflectionDynamicProxy {
    public static void main(String[] args) {
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println(method);
                if(method.getName().equals("morning")){
                    System.out.println("Good morning," + args[0]);
                }
                return null;
            }
        };
        Hello hello = (Hello) Proxy.newProxyInstance(
                Hello.class.getClassLoader(),
                new Class[] {Hello.class},
                invocationHandler);
        hello.morning("Pan3a");
    }
}

interface Hello{
    void morning(String name);
}

泛型

  • 泛型就是定义一种模板

使用泛型

  • 泛型类型实际上就是Object
  • 使用泛型时就是把<T>替换成需要的class类型
package com.pan3a.generics;

import java.util.Arrays;

public class GenericsInterface {
    public static void main(String[] args) {
        Person[] person = new Person[]{
                new Person("Pan3a",18),
                new Person("Forever404",20),
        };
        Arrays.sort(person);
        System.out.printf(Arrays.toString(person));
    }
}

class Person implements Comparable<Person>{
    String name;
    int score;

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

    public int compareTo(Person other){
        return this.name.compareTo(other.name);
    }

    public String toString(){
        return this.name + "," + this.score;
    }
}

编写泛型

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

    }
}
// 多泛型 class Pair<T, K>
class Pair<T>{
    private T first;
    private T last;

    public Pair(T first, T last){
        this.first = first;
        this.last = last;
    }

    public T getFirst(){
        return first;
    }

    public T getLast(){
        return last;
    }

//    静态方法使用泛型
    public static <K> Pair<K> create(K first, K last){
        return new Pair<K>(first,last);
    }
}

擦拭法

  • 泛型实现方式是擦拭法(Type Erasure)。
  • Java的泛型是由编译器在编译时实行的,编译器内部永远把所有类型T视为Object处理,但是,在需要转型的时候,编译器会根据T的类型自动为我们实行安全地强制转型。
  • 局限一,<T>不能是基本类型,例如int,因为实际类型是ObjectObject类型无法持有基本类型。必须是如<Intager>
  • 局限二,无法取得泛型的Class。
  • 局限三,无法判断带泛型的类型
  • 局限四不能实例化<T>类型,因为编译器会把<T>看成<Object>
package com.pan3a.generics;
import java.lang.reflect.Type;
import java.lang.reflect.ParameterizedType;

public class GenericsErasure {
    public static void main(String[] args) {
        Pair<String> pairOne = new Pair<>("Hello","World");
        Pair<Integer> pairTwo = new Pair<>(123,456);
        Class classOne = pairOne.getClass();
        Class classTwo = pairTwo.getClass();

        System.out.println(classOne == classTwo);
        System.out.println(classOne == Pair.class);

/*      泛型类无法判断其类型比如String,Integer
        if (pairOne instanceof pairTwo){
            System.out.println("");
        }
 */

//        泛型类继承
        Class<IntPair> clazz = IntPair.class;
        Type type = clazz.getGenericSuperclass();
        if (type instanceof ParameterizedType){
            ParameterizedType parameterizedType = (ParameterizedType) type;
            Type[] types = parameterizedType.getActualTypeArguments();
//            可能有多个泛型类型
            Type firstType = types[0];       //获取第一个泛型类
            Class<?> typeClass = (Class<?>) firstType;
            System.out.println(typeClass);
        }
    }
}


class Pair<T>{
    private T first;
    private T last;

    public Pair(T first,T last){
        this.first = first;
        this.last = last;
    }

    public T getFirst(){
        return first;
    }

    public T getLast(){
        return last;
    }
}

class IntPair extends Pair<Integer> {
    public IntPair(Integer first, Integer last) {
        super(first, last);
    }
}

extends通配符

  • <? extends Number>通配符方法。
  • 引用通配符方法时,Number number = Object.getFirst();这里的Number不能为integer,这样可能因为读取出来的是Double类型导致类型不匹配而报错。
  • 使用extends时表示可读不可写。
package com.pan3a.generics.extend;

public class GenericsExtends {
    public static void main(String[] args) {
        Pair<Integer> pair = new Pair<Integer>(123,456);
        int n = add(pair);
        System.out.println(n);
    }

  //  static int add(Pair<Number> p)  这样也会报错无法识别因为Pair<Integer>不是Pair<Number>的子类
    static int add(Pair<? extends Number> pair){
        Number first = pair.getFirst();
        Number last = pair.getLast();
//        这里会直接编译错误,因为我们如果传入的是Double setFirst是Integer型 因此会出现类型不匹配
//        pair.setFirst(new Integer(first.intValue() + 100));
        return first.intValue() + last.intValue();
    }
}

class Pair<T>{
    private T first;
    private T last;

    public Pair(T first, T last){
        this.first = first;
        this.last = last;
    }

    public T getFirst(){
        return first;
    }

    public T getLast(){
        return last;
    }

    public void setFirst(T first){
        this.first = first;
    }

    public void setLast(T last){
        this.last = last;
    }
}

super通配符

  • <? super Integer>通配符方法。
  • 可以调用传入Integer引用的方法,例如:obj.setFirst(Integer n);
  • super通配符表示只能写不能读。
  • 无限定通配符<?>很少使用,可以用<T>替换,同时它是所有<T>类型的超类。
package com.pan3a.generics.supers;

public class GenericsSuper {
    public static void main(String[] args) {
        Pair<Number> pairOne = new Pair<>(12.3, 45.6);
        Pair<Integer> pairTwo = new Pair<>(123, 456);
        setSame(pairOne,100);
        setSame(pairTwo,200);
        System.out.println(pairOne.getFirst() + " " + pairOne.getLast());
        System.out.println(pairTwo.getFirst() + " " + pairOne.getLast());
    }

    static void setSame(Pair<? super Integer> pair,Integer integer){
        pair.setFirst(integer);
        pair.setLast(integer);
    }
}

class Pair<T>{
    private T first;
    private T last;

    public Pair(T first, T last){
        this.first = first;
        this.last = last;
    }

    public T getFirst(){
        return first;
    }

    public T getLast(){
        return last;
    }

    public void setFirst(T first){
        this.first = first;
    }

    public void setLast(T last){
        this.last = last;
    }
}

无限定通配符

  • <?>既不能读也不能写。
  • Pair<?>Pair<T>的超类,因此可以向上转型。
public class main{
      public static void main(String[] args) {
        Pair<Integer> p = new Pair<>(123, 456);
        Pair<?> p2 = p; // 安全地向上转型
        System.out.println(p2.getFirst() + ", " + p2.getLast());
    }
}
class Pair<T> {
    private T first;
    private T last;

    public Pair(T first, T last) {
        this.first = first;
        this.last = last;
    }

    public T getFirst() {
        return first;
    }
    public T getLast() {
        return last;
    }
    public void setFirst(T first) {
        this.first = first;
    }
    public void setLast(T last) {
        this.last = last;
    }
}

泛型与反射

集合

List

  • List可添加重复元素和null,有ArrayList和LinkedList优先使用前者。
  • 遍历时使用for each或者Iterator,推荐使用前者,操作简单。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class collectionList {
    public static void main(String[] args) {
        List<String> list = addList();
        forList(list);
        iterationList(list);
        forEachList(list);
        String[] array = listToArray(list);
        arrayToList(array);
    }

    static void createList(){
//        JDK9  这里不接受null
//        List<Integer> list = List.of(1,2,3);
    }

    static List<String> addList(){
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("pear");
        list.add("apple");
        list.add(null);
        System.out.println(list.size());
        String second = list.get(3);
        System.out.println(second);
        return list;
    }

    static void forList(List<String> list){
        System.out.println("For循环遍历");
        for(int count=0; count<list.size(); count++){
            String string = list.get(count);
            System.out.println(string);
        }
    }

    static void iterationList(List<String> list){
        System.out.println("Iteration迭代遍历");
        for(Iterator<String> iterator = list.iterator(); iterator.hasNext();){
            String string = iterator.next();
            System.out.println(string);
        }
    }

    static void forEachList(List<String> list){
        System.out.println("for each 遍历");
        for(String string:list){
            System.out.println(string);
        }
    }

    static String[] listToArray(List<String> list){
        System.out.println("List转换成Array");
        String[] array = list.toArray(new String[list.size()]);
//      数字的话等价 Number可兼容其他类型   Number[] array = list.toArray(Number[]::new);
        for (String string:array){
            System.out.println(string);
        }
        return array;
    }

    static void arrayToList(String[] array){
        System.out.println("Array转换成List");
//        这里返回的是个只读List 无法add remove
        List<String> list = Arrays.asList(array);
        System.out.println(list);
    }
}

编写equals

  • Listcontains()判断是否包含某个变量、indexOf()获取变量所处序号位置。
  • List中查找元素时,List的实现类通过元素的equals()方法比较两个元素是否相等,因此,放入的元素必须正确覆写equals()方法,Java标准库提供的StringInteger等已经覆写了equals()方法,如果不在List中查找元素,就不必覆写equals()方法。
  • 确定两个实例是否相等首先用instanceof判断是否是Object类型,对引用类型用Objects.equals()比较,对基本类型直接用==比较。
  • 如果不调用Listcontains()indexOf()这些方法,那么放入的元素就不需要实现equals()方法。
package com.pan3a.collection.equals;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class collectionEquals {
    public static void main(String[] args) {
        List<String> stringList = new ArrayList<>();
        stringList.add("A");
        stringList.add("B");
        System.out.println(stringList.contains("A"));
        System.out.println(stringList.contains("C"));
//        因为Java内部String类实现类equals方法不是===对比,因此为true
        System.out.println(stringList.contains(new String("A")));

        System.out.println("---------------------");

        System.out.println(stringList.indexOf("A"));
        System.out.println(stringList.indexOf("C"));
        System.out.println(stringList.indexOf(new String("A")));

        System.out.println("----------------------");

        List<Person> list = new ArrayList<>();
        list.add(new Person("Pan3a","Pan3a",18));
        list.add(new Person("Forever404","Forever404",20));
        System.out.println(list.contains(new Person("Pan3a","Pan3a",18)));
        System.out.println(list.indexOf(new Person("Forever404","Forever404",20)));
    }

}

class Person{
    String firstName;
    String lastName;
    int age;

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

//    因为Person类没有系统自带的equals方法因此需要自己写  而String Integer这些Java标准库已经实现类equals方法
    public boolean equals(Object object){
        if(object instanceof Person){
            Person person = (Person) object;
            return Objects.equals(this.firstName,person.firstName) && this.age == person.age && Objects.equals(this.lastName,person.lastName);
        }
        return false;
    }
}

编写Map

  • 类似于字典的key,value对应。
package com.pan3a.collection.map;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class collectionMap {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("apple",123);
        map.put("pear",456);
        forEachKey(map);
        forEachEntrySet(map);
        testMap();
    }

    static void forEachKey(Map<String, Integer> map){
        for (String key : map.keySet()){
            Integer value = map.get(key);
            System.out.println(key + " = " + value);
        }
    }

    static void forEachEntrySet(Map<String, Integer> map){
        System.out.println("--------EntrySet--------");
        for (Map.Entry<String, Integer> entry : map.entrySet()){
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + " = " + value);
        }
    }

    static void testMap(){
        List<Student> list = new ArrayList<>();
        list.add(new Student("Bob",77));
        list.add(new Student("Pan3a",89));
        list.add(new Student("Forever404",79));
        Students students = new Students(list);
        System.out.println(students.getScore("Bob") == 77 ? "测试成功" : "测试失败");
        System.out.println(students.getScore("Tom") == -1 ? "测试成功" : "测试失败");
        System.out.println(students.findInList("Bob"));
    }
}

class Student{
    String name;
    int score;

    Student(String name, int score){
        this.name = name;
        this.score = score;
    }
}
class Students{
    List<Student> list;
    Map<String, Integer> cache;

    Students(List<Student> list){
        this.list = list;
        cache = new HashMap<>();
    }

    /*
    * 根据name查找score,找到返回score,未找到返回-1
     */
    int getScore(String name){
        Integer score = this.cache.get(name);
        if(score == null){
            //
        }
        return score == null ? -1 : score.intValue();
    }

    Integer findInList(String name){
        for(Student student : this.list){
            if (student.name.equals(name)){
                return student.score;
            }
        }
        return null;
    }
}

编写equals和hashCode

  • HashMap,作为key的类必须正确覆写equals()hashCode()方法;
    一个类如果覆写了equals(),就必须覆写hashCode(),并且覆写规则是:
    • 如果equals()返回true,则hashCode()返回值必须相等;
    • 如果equals()返回false,则hashCode()返回值尽量不要相等。

实现hashCode()方法可以通过Objects.hashCode()辅助方法实现。

package com.pan3a.collection.hashcode;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class collectionHashCode {
    public static void main(String[] args) {
        String string = new String("Hello");
        String test = new String("Hello");
        System.out.println(string.hashCode());
        System.out.println(test.hashCode());
        System.out.println(string.equals(test));
        System.out.println(string == test);

        System.out.println("-------hashcode && equals------");
        Person personOne = new Person("Pan3a",18);
        Map<Person,Integer> map = new HashMap<>();
        map.put(personOne,123);
        Person personTwo = new Person("Pan3a",18);
        System.out.println(personOne == personTwo);
        System.out.println(personOne.equals(personTwo));
        System.out.println(map.get(personOne));
        System.out.println(map.get(personTwo));
    }
}

class Person{
    public String name;
    public int age;

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

    @Override
    public int hashCode(){
        return Objects.hashCode(age) + Objects.hashCode(name);
    }

    @Override
    public boolean equals(Object object){
        if(object instanceof Person){
            Person person = (Person) object;
            return Objects.equals(this.name,person.name) && this.age == person.age;
        }
        return false;
    }
}

编写EnumMap

  • 如果Map的key是enum类型,推荐使用EnumMap,既保证速度,也不浪费空间。使用EnumMap的时候,根据面向抽象编程的原则,应持有Map接口。
import java.time.DayOfWeek;
import java.util.EnumMap;
import java.util.Map;

public class collectionEnumMap {
    public static void main(String[] args) {
        Map<DayOfWeek,String> map = new EnumMap<>(DayOfWeek.class);
        map.put(DayOfWeek.MONDAY,"星期一");
        map.put(DayOfWeek.TUESDAY,"星期二");
        map.put(DayOfWeek.WEDNESDAY,"星期三");
        map.put(DayOfWeek.TUESDAY,"星期四");
        map.put(DayOfWeek.FRIDAY,"星期五");
        map.put(DayOfWeek.SATURDAY,"星期六");
        map.put(DayOfWeek.SUNDAY,"星期日");
        System.out.println(map);
        System.out.println(map.get(DayOfWeek.MONDAY));
    }
}

使用TreeMap

  • SortedMap在遍历时严格按照Key的顺序遍历,最常用的实现类是TreeMap;作为SortedMap的Key必须实现Comparable接口,或者传入Comparator;要严格按照compare()规范实现比较逻辑,否则,TreeMap将不能正常工作。
package com.pan3a.coolestions.treemap;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;

public class collectionTreeMap {
    public static void main(String[] args) {
        sortingMap();
    }

    public static void test(){
        Map<String,Integer> map = new TreeMap<>();
        map.put("orange",1);
        map.put("apple",2);
        map.put("pear",3);
        for(String key: map.keySet()){
            System.out.println(key);
        }
    }

    public static void sortingMap(){
        Map<Person,Integer> map = new TreeMap<>(new Comparator<Person>() {
            @Override
            public int compare(Person personOne, Person personTwo) {
                if(personOne.score == personTwo.score){
                    return 0;
                }
                return personOne.score > personTwo.score ? -1 : 1;
            }
        });
        map.put(new Person("Pan3a",78),1);
        map.put(new Person("Forever404",89),2);
        map.put(new Person("Bob",62),3);
        for (Person key : map.keySet()){
            System.out.println(key);
        }
        System.out.println(map.get(new Person("Bob",62)));
    }
}


class Person{
    public String name;
    public int score;

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

    @Override
    public String toString(){
        return String.format("{%s: score=%d}",name,score);
    }
}

使用Properties

  • Java集合库提供的Properties用于读写配置文件.properties.properties文件可以使用UTF-8编码。
    可以从文件系统、classpath或其他任何地方读取.properties文件。
    读写Properties时,注意仅使用getProperty()setProperty()方法,不要调用继承而来的get()put()等方法。
import java.io.*;
import java.util.Properties;

public class collectionProperties {
    public static void main(String[] args){
        testRead();
        bytesCodeRead();
        testWrite();
    }

    public static void testRead(){
//        为啥相对路径不行
        String filePath = "/Users/pan3a/CodeProject/JavaProject/src/setting.properties";
        Properties properties = new Properties();

        try {
            properties.load(new FileInputStream(filePath));
        } catch (IOException exception) {
            exception.printStackTrace();
            System.out.println(exception);
        }

        String getFilePath = properties.getProperty("last_open_file");
//        设置默认值120 当不存在该配置时
        String getInterval = properties.getProperty("auto_sava_interval","120");

        System.out.println(getFilePath);
        System.out.println(getInterval);
    }

    public static void bytesCodeRead() {
        String settings = "# test" + "\n" + "course=Java" + "\n" + "last_open_date=2019-08-07T12:35:01";
        ByteArrayInputStream input = null;
        try {
            input = new ByteArrayInputStream(settings.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        Properties props = new Properties();
        try {
            props.load(input);
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("course: " + props.getProperty("course"));
        System.out.println("last_open_date: " + props.getProperty("last_open_date"));
        System.out.println("last_open_file: " + props.getProperty("last_open_file"));
        System.out.println("auto_save: " + props.getProperty("auto_save", "60"));
    }

    public static void testWrite() {
        Properties properties = new Properties();
        properties.setProperty("url","https://www.baidu.com");
        properties.setProperty("language","Java");
        try {
            properties.store(new FileOutputStream("/Users/pan3a/CodeProject/JavaProject/src/setting.properties"),"这是写入的注释");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用Set

  • Set用于存储不重复的元素集合:放入HashSet的元素与作为HashMap的key要求相同;放入TreeSet的元素与作为TreeMap的Key要求相同;利用Set可以去除重复元素;遍历SortedSet按照元素的排序顺序遍历,也可以自定义排序算法。
import java.util.*;

public class collectionSet {
    public static void main(String[] args) {
        testSet();
        treeSet();
    }

    static void testSet(){
        Set<String> set = new HashSet<>();
        System.out.println(set.add("Pan3a"));
        System.out.println(set.add("Forever404"));
        System.out.println(set.add("Pan3a"));

        System.out.println(set.contains("Pan3a"));
        System.out.println(set.remove("Panda"));
        System.out.println(set.size());
    }

    static void treeSet(){
        System.out.println("--------------------------");
        List<Message> messageList =  new ArrayList<>();
        messageList.add(new Message(1,"Hello!"));
        messageList.add(new Message(2,"发工资了吗"));
        messageList.add(new Message(2,"发工资了吗"));
        messageList.add(new Message(3,"中午吃啥子"));
        messageList.add(new Message(3,"中午吃啥子"));

        List<Message> displayMessages = process(messageList);
//        避免重复展示数据
        for (Message message : displayMessages){
            System.out.println(message.text);
        }
    }

    static List<Message> process(List<Message> received){
        Set<Message> messageSet = new TreeSet<>();
        List<Message> messageListTwo = new ArrayList<>();
        for(Message message : received){
            messageSet.add(message);
        }

        for (Message message : messageSet){
            messageListTwo.add(message);
        }

        return messageListTwo;
//        return received;
    }
}

class Message implements Comparable<Message>{
    public final int sequence;
    public final String text;

    Message(int sequence, String text) {
        this.sequence = sequence;
        this.text = text;
    }

    @Override
    public int compareTo(Message message) {
        if (this.sequence == message.sequence){
            return 0;
        }
        return this.sequence > message.sequence ? 1 : -1;
    }
}

使用Queue

  • 队列Queue实现了一个先进先出(FIFO)的数据结构:通过add()/offer()方法将元素添加到队尾;通过remove()/poll()从队首获取元素并删除;通过element()/peek()从队首获取元素但不删除。要避免把null添加到队列。
import java.util.LinkedList;
import java.util.Queue;

public class collectionQueue {
    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<>();
        queue.offer("apple");
        queue.offer("pear");
        queue.offer("banana");

        System.out.println(queue.poll());

        System.out.println(queue.element());
        System.out.println(queue.element());

        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
    }
}

使用PriorityQueue

  • PriorityQueue实现了一个优先队列:从队首获取元素时,总是获取优先级最高的元素。PriorityQueue默认按元素比较的顺序排序(必须实现Comparable接口),也可以通过Comparator自定义排序算法(元素就不必实现Comparable接口)。
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;

public class collectionPriorityQueue {
    public static void main(String[] args) {
        testPriorityQueue();
        testUserPriorityQueue();
    }

    public static void testPriorityQueue(){
        Queue<String> queue = new PriorityQueue<>();
        queue.offer("apple");
        queue.offer("pear");
        queue.offer("banana");

        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
    }

    public static void testUserPriorityQueue(){
        System.out.println("--------------------");
        Queue<User> queue = new PriorityQueue<>(new UserComparator());
        queue.offer(new User("Bob","A7"));
        queue.offer(new User("Alice","A2"));
        queue.offer(new User("Pan3a","V10"));
        queue.offer(new User("Jack","A3"));
        queue.offer(new User("Hack","V2"));
        int counts = queue.size();
        for(int count = 0; count < counts; count++) {
            System.out.println(queue.poll());
        }
    }
}

class User{
    public final String name;
    public final String number;

    public User(String name, String number){
        this.name = name;
        this.number = number;
    }

    @Override
    public String toString(){
        return name + "/" + number;
    }
}

class UserComparator implements Comparator<User> {
    @Override
    public int compare(User userOne, User userTwo) {
        if(userOne.number.charAt(0) == userTwo.number.charAt(0)){
            return userOne.number.compareTo(userTwo.number);
        }

        if (userOne.number.startsWith("V")){
            return -1;
        }else {
            return 1;
        }
    }
}

使用Deque

  • Deque实现了一个双端队列(Double Ended Queue),它可以:
    • 将元素添加到队尾或队首:addLast()/offerLast()/addFirst()/offerFirst()
    • 从队首/队尾获取元素并删除:removeFirst()/pollFirst()/removeLast()/pollLast()
    • 从队首/队尾获取元素但不删除:getFirst()/peekFirst()/getLast()/peekLast()
    • 总是调用xxxFirst()/xxxLast()以便与Queue的方法区分开;
    • 避免把null添加到队列。
import java.util.Deque;
import java.util.LinkedList;

public class collectionDeque {
    public static void main(String[] args) {
        Deque<String> deque = new LinkedList<>();
        deque.offerLast("A");
        deque.offerLast("B");
        deque.offerFirst("C");                  // C <= A <= B
        System.out.println(deque.pollFirst());
        System.out.println(deque.pollLast());
        System.out.println(deque.pollFirst());
    }
}

使用Stack

  • 栈(Stack)是一种后进先出(LIFO)的数据结构,操作栈的元素的方法有:
    • 把元素压栈:push(E)
    • 把栈顶的元素“弹出”:pop(E)
    • 取栈顶元素但不弹出:peek(E)

在Java中,我们用Deque可以实现Stack的功能,注意只调用push()/pop()/peek()方法,避免调用Deque的其他方法。
最后,不要使用遗留类Stack

使用Iterator

  • Iterator是一种抽象的数据访问模型。使用Iterator模式进行迭代的好处有:
    • 对任何集合都采用同一种访问模型;
    • 调用者对集合内部结构一无所知;
    • 集合类返回的Iterator对象知道如何迭代。

Java提供了标准的迭代器模型,即集合类实现java.util.Iterable接口,返回java.util.Iterator实例

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class collectionIterator {
    public static void main(String[] args) {
        ReverseList<String> reverseList = new ReverseList<>();
        reverseList.add("Apple");
        reverseList.add("Orange");
        reverseList.add("Pear");
        for (String string : reverseList){
            System.out.println(string);
        }
    }
}

class ReverseList<T> implements Iterable<T>{
    private List<T> list = new ArrayList<>();

    public void add(T t){
        list.add(t);
    }

    public Iterator<T> iterator(){
        return new ReverseIterator(list.size());
    }

    class ReverseIterator implements Iterator<T>{
        int index;

        ReverseIterator(int index){
            this.index = index;
        }

        @Override
        public boolean hasNext() {
            return index > 0;
        }

        @Override
        public T next() {
            index--;
            return ReverseList.this.list.get(index);
        }
    }
}

使用Collections

  • Collections类提供了一组工具方法来方便使用集合类:
    • 创建空集合;
    • 创建单元素集合;
    • 创建不可变集合;
    • 排序/洗牌等操作。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class collectionCollections {
    public static void main(String[] args) {
        testCollections();
        mutableCollections();
    }

    public static void testCollections(){
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("pear");
        list.add("orange");

        System.out.println(list);
//        排序
        Collections.sort(list);
        System.out.println(list);
//        随机顺序
        Collections.shuffle(list);
        System.out.println(list);
    }

    public static void mutableCollections(){
        System.out.println("---------------------");
        List<String> mutable = new ArrayList<>();
        mutable.add("apple");
        mutable.add("pear");
        List<String> immutable = Collections.unmodifiableList(mutable);
        mutable.add("orange");
        System.out.println(immutable);
    }
}
posted @ 2021-10-15 14:49  Pan3a  阅读(128)  评论(0编辑  收藏  举报