AI智能
改变未来

JavaStudy


JavaBasic

  • 创建的文件名需与类名一致,即
    HelloWorld.java

    ,严格要求大小写。

  • 主函数参数可为
    String args[]

    String[] args

  • 一个源文件只能有一个
    public

    类,且仅为文件名相同的类为

    public

    属性。

  • java

    文件运行是

    javac

    Hello.java

    文件编译成

    Hello.class

    的字节码,然后由

    jvm

    虚拟机对其进行解释执行。

public class HelloWorld{public static void main(String[] args){System.out.println("Hello World")}}

访问控制符

  • private

    default

    protected

    public

    四个标识符。| | 同一个类中 | 同一个包中 | (不同包)子类中 | 全局范围内 || — | — | — | — | — || 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

  • 这里的
    StringBuffer

    StringBuilder

    来由是因为平常创建的字符串在修改的时候是重新创建的一个对象,而不是原字符串。后者没有线程安全,但是相比前者后者有速度优势,因此大多数情况下建议使用后者。

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() {// 重载方法,过滤不需要的文件@Overridepublic 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();//        如果代码出错,并不会回收输入流,可用tryreadFile();//        一次读取一个字节不高效,因此可以使用缓冲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!");}elseSystem.out.println("Hello " + name + ", you are a child!");}}

继承

  • 子类无法继承父类的构造方法
  • 子类的构造方法必须与父类的构造方法类型一致   如:无参对应无参
  • 子类的构造方法第一条语句必须是父类构造方法
  • 只能单继承,除Object外没有关键字
    extends

    的类都是继承于

    Object
  • Java15特性,
    sealed

    permits

    修饰的类只能在指定的类继承

  • 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{@Overridepublic 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{@Overridepublic 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);}@Overridepublic double getTax() {if (income <= 5000){return 0;}return (income - 5000) * 0.2;}}// 国家补贴免税收class StateCouncilSpecialAllowance extends Salary{public StateCouncilSpecialAllowance(double income){super(income);}@Overridepublic 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);}@Overridepublic void run(){System.out.println("Student run");}public void say(){System.out.println("Hello " + this.name);}@Overridepublic 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;}@Overridepublic void say(){System.out.println("Hello World!");}@Overridepublic String getName(){return this.name;}@Overridepublic void red(){System.out.println("this is hello method!");}@Overridepublic 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(){@Overridepublic 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);}@Overridepublic 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";@Overridepublic 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.forNameClass class1 = Class.forName("com.pan3a.reflection.Person");System.out.println("别名:" + class1.getSimpleName());System.out.println(class1);//      类名.classClass 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);}}

成员变量

  • 获取成员变量需要知道一下四个方法,
    getField

    getFields

    getDeclaredField

    getDeclaredFields

  • 还可获取成员变量属性的三个方法,
    getType

    getModifiers

    getName

    。分别是获取变量类型,修饰符,成员名。

  • 他们分别是获取单个成员,和获取所有成员,获取单个成员(忽略修饰服限制,不包括父类),获取多个成员(忽略修饰服限制,不包括父类)。需注意的是使用后面两个是需使用
    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);}}

成员方法

  • 获取成员方法如通获取成员变量类似,也有四个方法。
    getMethod

    getMethods

    getDeclaredMethod

    getDeclaredMethods

  • 获取方法属性,
    getName

    getReturnType

    getParameterTypes

    getModifiers

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为nullMethod 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() {@Overridepublic 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

    ,因为实际类型是

    Object

    Object

    类型无法持有基本类型。必须是如

    <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,Integerif (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 removeList<String> list = Arrays.asList(array);System.out.println(list);}}

编写equals

  • List

    contains()

    判断是否包含某个变量、

    indexOf()

    获取变量所处序号位置。

  • List

    中查找元素时,

    List

    的实现类通过元素的

    equals()

    方法比较两个元素是否相等,因此,放入的元素必须正确覆写

    equals()

    方法,Java标准库提供的

    String

    Integer

    等已经覆写了

    equals()

    方法,如果不在

    List

    中查找元素,就不必覆写

    equals()

    方法。

  • 确定两个实例是否相等首先用
    instanceof

    判断是否是Object类型,对引用类型用

    Objects.equals()

    比较,对基本类型直接用

    ==

    比较。

  • 如果不调用
    List

    contains()

    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方法不是===对比,因此为trueSystem.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;}@Overridepublic int hashCode(){return Objects.hashCode(age) + Objects.hashCode(name);}@Overridepublic 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>() {@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic String toString(){return name + "/" + number;}}class UserComparator implements Comparator<User> {@Overridepublic 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 <= BSystem.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;}@Overridepublic boolean hasNext() {return index > 0;}@Overridepublic 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);}}
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » JavaStudy