Java学习笔记(个人向)


1. 概述

  • 每一个应用程序都以类名开头 ,类名必须与文件名匹配,所以保存文件时,要使用类名保存;

  • java中运行的每一行代码都必须在一个class中;

  • 在类名的开头,可以用权限修饰符来解释,如private或者public

  • main()方法是必需的,每一个Java程序都有

  • main()方法中的任何代码都会被执行

  • 对于xxx类中的main()方法中的方法(函数),相当于嵌套调用;

  • 可以使用println()方法将一行文本打印到屏幕上,如:

    java 复制代码
    public static void main(String[] args) {
        System.out.println("Hello World");
    }  
  • 同样,与c++一致,大括号表示代码块的开始和结束;

  • 每个代码语句必须用分号结尾;

2. 注释

  • 单行注释以//开头,java将默认忽略//和行尾之间的任何文本;
  • 多行注释以/*开头,*/结尾,同样两者之间的文本会被Java忽略;

3. 变量类型

  • 变量是存储数据的容器;

  • Java的变量类型有:

    1. string:文本,字符串;
    2. int:有符号数;
    3. float:浮点数;
    4. char:存储单个字符,通过"......"的形式接收,当然'......'也行;
    5. boolean:存储布尔值,有truefalse两种;
  • 建立变量:

    • 指定类型 (+ 赋值);
      type variable (= value);

    • 一般情况下,新的赋值会覆盖掉旧的赋值,如果要避免这种情况,可以使用final关键字声明在变量定义前面,如:

      java 复制代码
      final int num=1; 

    这样会将变量设置为只读不可写;

  • 我们可以使用System.out.println()的方式用于显示变量;

  • 如果要一次性声明多个同样类型的变量,可以用,隔开,如int i1=1,i2=2;

  • java的变量名不应包含空格;

  • 理论上可以使用$_开头;

  • java的名称区分大小写;

  • system默认的关键字不要用做变量名,不然会覆盖掉原有设置好的;

4. 数据类型

  1. 基本数据类型 byte,short之类的;
  2. 非基本数据类型 String,ArraysClasses
  • 基本八种:

    数据类型 大小 描述
    byte 1B 有符号二进制数
    short 2B 范围小有符号数
    int 4B 范围适中的有符号数
    long 8B 范围较大的有符号数
    float 4B 范围适中的浮点数
    double 8B 范围较大的浮点数
    boolean 1b,即一位 存储truefalse
    char 2B 存储单个字符
  • 对对应数据类型赋值时,应当在数值末尾加上对应的类型符,如long---L,float---f,double---d;

  • boolean型的取值只能是true或者false;

  • 浮点数用e表示10的幂,如12e9=12*10^9;

  • 字符的要求,赋值时推荐:字符用单引号,字符串用双引号 ; 注意,字符串的string要写成大写的String,而且它不是原始数据类型,因为使用它的时候需要引用到一个对象;

  • 创建的原始类型始终会有数值,而非原始类型则可以以null填充;

  • 原始类型的大小取决于数据类型,而非原属类型的大小都是相同的(相对固定);

5. 数据类型转换

  1. 隐式类型转换
    • 自动完成,思路是:通过以零补位的形式实现
    • byte-->short-->char-->int-->long-->float-->double;
  2. 强制类型转换
    • 手动完成,需要强制转换符(......)
      如:int myInt = (int)myDouble;
    • 顺序与上边相反的,将较小的类型转换为较小的类型,需要使用强制转换;

6. 运算符

  • 用于对变量和值执行操作;
  • 包括:
    1. 算术运算符;
    2. 赋值运算符;
    3. 关系运算符;
    4. 逻辑运算符
    5. 位运算符
  • %取模;
  • ++自加1,--自减1;
  • +=自加,-=自减,/=自除,|=位或运算,^=异或运算,&=位并运算,>>=无符号部分右移得到移码无符号部分左移得到移码
  • ==等于,!=不等于;
  • &&逻辑与、||逻辑或、!逻辑非;
  • &位交,|位并,~位取反,^位异或,<<左移码,>>右移码,>>>右移码并补零;

7. 字符串

  • 用字符串结构String来存储文本,用双引号包围的字符来传值;
  • 关于字符串有以下几种方法:
    1. 字符串长度:.length()返回;
    2. 大小写转换:toUpperCase()将字符串转变成大写,toLowerCase()将字符串转变成小写;
    3. 查找字符串第一次出现的位置:indexOf()返回第一次出现的位置学了数据结构的都知道从零开始);
    4. 串联:用+可以连接前后两个字符串、又或者使用<前者>.concat(<后者>)的方法;
  • 特殊字符必须写在引号内,否则Java会误解此字符串的性质,并生成错误。
  • 为了避免',",\被系统误以为有实际功能,可以使用反斜杠\将特殊字符转换为字符串;
  • 除此以外,还有一些特殊的转义字符:
    1. \n:换行;
    2. \r:回车;
    3. \t:制表;
    4. \b:空格;
    5. \f:换页;

注意:如果是一个数字和一个字符串执行+操作,则数字部分会被强制转化为字符串进行运算。

8. 数学方法(内置)

Math类的方法

  1. max(x,y):用于查找xy的最大值;
  2. min(x,y):用于查找xy的最小值;
  3. sqrt(x):用于返回x的平方根;
  4. abs(x):用于返回x的绝对值;
  5. random():返回一个介于[0.0,1.0)的随机数,至于如果你要0到10^k之间的随机数,可以用上述随机数乘以10^k+1来获得;

所有的数学方法都是static静态的;

9. 条件语句

  • 使用方法基本和C++差不多;

  • 以下介绍三元运算符

    java 复制代码
    variable=(condition)? expressionTrue:expressionFalse;

    其中前者的表达式是条件为真使用的,后边是条件为假使用的。

10. 选择语句

  • switch......case型;

  • 格式为:

    java 复制代码
    switch(expression){
        case x:  
            代码块1;  
            (break;)  
        case y:  
            代码块2;  
            (break;)
        ····
        (default:  
            代码块n;)
    }
  • 意思为:

    1. switch先计算一次;
    2. case将计算的结果和每个case后的情况进行条件比较。如果符合的话执行后边相关的代码块;
    3. breakdefault是可有可无的;
  • 中断关键字

    1. break:停止在块内执行,并跳出所在的程序块;
    2. default设置默认值兜底;
  • 关键点:

    1. expression必须是整数、字符、字符串、枚举或者是它们的表达式;
    2. break用于跳出switch语句,没有它会导致继续执行下一个case代码块。所以通常在每一个case语句的末尾添加break
    3. default少用,建议在处理不期望的输入时使用它。

11. 循环语句

  • 基本和c++的一样;
java 复制代码
  for(代码块第一次执行前执行一次;判断代码块是否执行的条件;代码块执行后执行){  
      代码块
  }
  • 除此以外,还有for-each循环,它专门用于循环在数组Array中的元素。

    java 复制代码
    X型数组A=(A1,A2,...);  
    for (X型值i : A){  
        代码块
    }

    典型的有:

    java 复制代码
    String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
    for (String i : cars) {
        System.out.println(i);
    }
  • break跳出循环,continue跳出本轮循环。他们俩常配置着循环语句使用。

12. 数组

  • 用方括号定义变量类型并声明数组:

    java 复制代码
    数组类型[] 数组名;
  • 数组赋的值框在大括号{···}里。

  • 与C++一样,访问元素用索引,索引从0开始;

  • 更改数组元素,可以用索引赋值;

  • 数组有方法.length可以返回数组有多少个元素;

  • for循环常用于遍历数组,不过for-each可读性更强,更推荐使用;

  • 可以通过将数组当成一个元素嵌套到新的数组的方式实现多维数组,如{{1,2},{3,4}}且索引方式也是一级一级打开; 对于多维数组的遍历,多个for循环是不错的方法;

13. 方法(函数)

  • 由于java所有的文件都是类文件(有大有小),所以方法必须在类里边申明。
  • 方法使用名称来定义的,后面跟上{代码块};
  • 方法的调用通过方法名配合必要的参数;
  • 一个方法可以被多次调用;
  • 可以在方法名后增加()的方式来传递参数,申明时也要标准形参的数据类型,不同参数之间用,隔开。
  • 当参数被传递给方法后,就从形参转化为实参
    也就是它被实体化了。
  • 在申明方法时,我们会顺便申明返回值的情况。此处可以用返回值的数值类型说明。与C++一样,返回值用return传递。如果是不需要返回值,用void申明;

14. 重载

  • 使用方法重载,可以使多个方法拥有相同的名称和不同参数,便于理清思路和展示联系;
  • 与其定义两个应该做相同事情的方法,不如直接重载一个;
  • 这里就体现java的方法都在类里定义的好处了。重载不需要再像C++一样有特殊的operator运算符,直接下边重写就可以了。
  • 只要参数的数量或者类型不同,多个方法就可以具有相同的名称

15. 作用域

  • 在Java中,变量只能够在创建的区域内访问,区域称之为作用域;
  • 方法内申明的,申明语句后的语句都可以使用;
  • 代码块内申明的变量,只能够由大括号之间的代码访问,且在申明后方可使用;

16. 递归

  • 对于函数来说,是自己传值给自己,以实现数学上的递归或者说回归,最后企图得到(可能存在的)不动点。
  • 为了防止递归没完没了,显然递归函数都必须要有合理的停止条件,即必须要有能够跳出循环的判断条件;

17. OOP/面向对象编程

  • 即同时创建包含的数据和函数的对象,以对象为操作和访问的基本逻辑单位;
  • 有利于多态,封装和模块化,提供了清晰的结构。
  • 体现了局部性原理的思想;
  • 类是对象的模板,对象是类的实例;
  • 对象将继承类中的所有变量和方法;

18. 类

  • 在java的语法中,类始终以大写字母开头,类名应该要与文件名相匹配。

  • 与C++一样,类的申明由class关键字开始,类的权限则出现在一开头class的左边。

  • 对象的创建:

    java 复制代码
    类名 对象名 = new 类名(可能的传参);

    其中等号的后半部分是为了申明该对象需要分配的物理存储空间;

  • 一个类可以创建多个对象。

  • 还可以创建一个类的对象并在另一个类中访问它。这有利于更快地组织类(一个类拥有所有的方法和属性(变量),另一个类则含有main()方法;

在命令行中,需要用:

java 复制代码
javac 对象名.java//编译文件
java 对象名//执行文件
  • 对于类中的变量,与C++一直,可以使用.取值符来访问,而且可以在新生成的对象中修改它,但只对对象自己有效 。这样看来,类中赋值了的属性,字段或者说变量更像是default默认值一般的存在。
  • 如果你不想类中的属性值随意的被对象更改掉,可以在申明的时候添加final关键字锁死。

19. 类方法

  • 调用格式:对象名.方法名();
  • 经常可以看到具有static静态和public公共属性和方法的Java程序;
    1. static:可以在不创建类的对象的情况下访问该方法,例如Math中的数学计算方法都是static的就是这个原因;
    2. public:只能用对象来访问方法;
  • 为了使用public的类方法,我们必须先创建对象再调用。
  • .用于访问对象的属性和方法
  • 将方法实行和方法建立分散到对应的类和类中的对象中,是很不错的技巧。

20. 构造函数

  • 是一种用于初始化对象的特殊方法

  • 在创建类对象的时候会调用构造函数;

  • 它常用于设置对象属性的初始值,等于说原来类的属性是没赋值的,现在创建对象的时候再赋值;

  • 【注意】:构造函数的名称必须与类名相匹配,且不能有返回值 ,最好直接是void;

  • 但理论上,所有类在创建对象的时候都是有构建函数,只是类中赋值的对象无法设置对象属性的初始值;

  • 典型例子:

    java 复制代码
    public class MyClass {
        int x;
    
        public MyClass(int y) {
            x = y;
    }
    
        public static void main(String[] args) {
        MyClass myObj = new MyClass(5);
        System.out.println(myObj.x);
        }
    }
    
    // 输出 5

21. 修饰符

  • 用于设置类、属性、方法和构造函数的访问级别
  • 一般分为两类:
    1. 访问修饰符 :控制访问级别;
    2. 非访问修饰符 :不控制访问级别,提供其他功能;
  • 对于class常用的修饰符有:
    1. 访问修饰符
      1. public:任何类都可以访问;
      2. default:只能由同一包中的类访问(一般出现在不指定修改器);
    2. 非访问修饰符
      1. final:该类不能被其他类继承(和用在属性上一样,表示不改了);
      2. abstract:该类被抽象了出来,自身不能创建对象,只能通过继承的方式创建;
  • 对于attribute或者meansconstructor来说:
    1. 访问修饰符
      1. public:所有类都可以访问;
      2. private:只能该类内部访问,即通过类的方法 ,其他类无法直接访问属性(便于实现封装、隐藏内部实现细节,提高代码的安全性和可维护性);
      3. default:该类只能由同一包中的类进行访问,在不指定修改器时使用;
      4. protected:代码可以在相同包,和子类中访问;
    2. 非访问修饰符
      1. final;
      2. static:属性和方法属于类而不是对象;
      3. abstract:只能在抽象类中使用,且只能在方法上使用,即主体部分只能由生成的对象提供。
      4. transient*:序列化 包含属性和方法的对象时,将跳过属性和方法
        • 在Java中,序列化(Serialization)是指将对象的状态转换为字节流 的过程,从而可以将对象保存到文件、数据库或通过网络传输给其他Java虚拟机(JVM)。反序列化(Deserialization)是将字节流转换回对象的过程。序列化的主要作用是持久化对象状态和对象之间的远程通信。
        • 关键点:
          1. 实现Serializable接口:要使一个Java对象可以序列化,该类必须实现java.io.Serializable接口。
          2. 序列化过程:使用ObjectOutputStream类的writeObject()方法将对象转换为字节流。
          3. 反序列化过程:使用ObjectInputStream类的readObject()方法将字节流转换回对象。
          4. transient关键字:用transient关键字修饰的字段不会被序列化。
      5. volatile:属性值不是本地缓存的线程,总是从主存中读取
        • 用于修饰变量,确保在多个线程间对该变量的读写操作的可见性。它的主要作用是保证变量的可见性和防止指令重排序。
          主要用途:
          1. 变量的可见性:
            • 当一个变量被声明为volatile时,Java内存模型保证所有线程都能看到该变量的最新值。当一个线程修改了volatile变量的值,新值会立即被刷新到主内存中,其他线程读取时可以立即获得最新值
          2. 防止指令重排序:
            • volatile变量在读取和写入时都会插入内存屏障(memory barrier),这可以防止编译器和处理器对这些操作进行重排序,从而保证了代码执行的顺序一致性。

22. 封装

  • 步骤:
    1. 将类变量/属性声明为private;
    2. 提供公共 getset方法 来访问和更新private私有变量的值;
    3. get方法返回变量值,set方法设置值,两者的语法都是以getset开头,后跟变量名,第一个字母大写;
  • 意义:
    1. 类属性可以设置为只读(如果只使用get方法),也可以设置为只写(如果只使用set方法);
    2. 提高数据的安全性;
    3. 可以在不影响其他部分的情况下更改代码的一部分;

23. 包(package

  • Java 中的包用于对相关类进行分组。可将其视为文件目录中的文件夹
  • 我们使用包来避免名称冲突,并编写更好的可维护代码。
  • 分为两类:
    1. 内置包(来自Java API的包);
    2. 用户定义的包(创建自己的包);

API

  • Java API 是Java开发环境中包含的一个预编写类库,该库分为包和类,可以免费使用;
  • 完整列表可在Oracles网站上找到;
  • 该库包含用于管理输入、数据库编程等的组件;
  • 要使用库中的类和包,需要使用import关键字;
  • 使用
    1. 导入
      1. 导入包中的某个类:import <packagename>.<classname>,而且要使用导入的类需要创建该类的对象;
      2. 导入整个包:import <packagename>.*;
    2. 创建自己的包
      • 使用package关键字

      • 格式:

        java 复制代码
        package <自定义包名>  
        class <自建类>{......}  
      • 将上面的文件另存为后编译 ,这将强制编译器创建"自定义包名"的包 -d 关键字指定保存类文件的目标位置,空格后可以直接跟地址也可以直接跟.表示在同一目录下(linux)。

      • 要使用创建包中的类,在命令行中使用java <自定义包名>.<自建类>;

24. 继承

  • Java 中可以将属性和方法从一个类继承到另一个类。
  • 继承分为两部分:
    1. 子类 (Subclass) - 子,从另一个类继承的类;
    2. 超类 (Superclass) - 父,被继承的类;
  • 要从类继承,请使用extends关键字

总结:访问权限

  1. private:仅在同一个类可访问;
  2. default(无修饰符):仅在同一个包中可访问;
  3. protected:在同一个包,以及不同包的子类中可以访问;
  4. public:在任何地方都可以访问;
    【注意】:protected成员在子类中可以重写,但在子类外部(即使是子类的实例)不能直接访问这些成员。
  • 子类对超类的继承,可以使用protected进行安全性的保障,但要注意子类的实例无法使用带该关键字的属性、方法。
  • 如果不想其他类从该类继承,同样使用final关键字;

25. 多态

  • 在子类继承超类时,除默认的超类中的属性、方法外,在代码块中每个子类可以定义属于自己的属性、方法;这种在属性、方法上的差异被解释成多态。
  • 也许不同子类的属性、方法名字也叫一样,但是这本质是功能的不同实现,busuanshi"重写";
  • 继承和多态的意义:对于代码的可重用性很有用,在创建新类时也可以重用现有类的属性和方法。

26. 内部类/嵌套类

  • 类中类
  • 嵌套类的目的是将属于同一类的类分组,这使代码更具可读性和可维护性;
  • 要访问内部类,请创建外部类的对象,然后创建内部类的对象(一层一层实体化);
  • 与常规类不同,常规类的访问关键字只能是public或者default两种,内部类新增加了privateprotected两种 。如果你想对类设置一些权限,可以采用内部类的方式,甚至直接private禁止访问。
  • 内部类也可以是static的,也就是静态的,属于类但不属于对象 ,这意味着可以在不创建外部类的对象的情况下访问它。 但是这与static静态属性、方法一样,static的内部类无法访问外部类的属性、方法
  • 内部类可以访问外部类的属性和方法;

27. 抽象类

  • 数据抽象是隐藏某些细节并仅向用户显示基本信息的过程。
  • 可以通过abstract class抽象类或interfaces接口来实现;
  • abstract关键字是非访问修饰符,用于类和方法:
    1. 抽象类 :不能直接创建对象,只能继承后创建;
    2. 抽象方法 :只能在抽象类中使用,自身没有主体代码块,主体代码块要继承的子类提供;
  • 抽象类中除了抽象方法也存在常规方法;

28. 接口

  • Java 中实现abstraction抽象的另一种方法是使用接口,实际上是高度抽象;

  • 接口,即interface关键字定义的部分,是一个完全抽象"类",它将相关方法和空实体分组 ,在接口中所有方法都没有主体代码块;

  • 要访问接口方式,需要创建一个由implements关键字引导"继承的类"。一般情况下,接口的方法在implement类中定义;

  • Java中的类只能继承一个父类,但可以实现多个接口,这实现了多重继承的效果。

  • 为了实现安全性-隐藏某些细节,只给对象(接口)显示重要细节,例如api

  • 一些性质的简要说明:

    1. 接口中的所有方法默认都是抽象的(即使不加abstract关键字);
    2. 和抽象类一样,接口不能用于创建对象;
    3. 接口方法没有主体,主体由implement类提供;
    4. 在实现接口时,必须重写其所有方法;
    5. 接口不能包含构造函数(因为它不能用于创建对象);
    6. 默认情况下,接口方法是abstract抽象的和public公共的;
    7. I接口属性默认为 public, staticfinal;
    8. 接口可以包含常量,所有的字段默认是public static final
  • 在Java中,接口(interface)是一种引用类型,用于定义一组抽象方法和常量。接口不能包含具体实现,具体的实现由实现接口的类提供。接口在Java中扮演着重要角色,特别是在设计良好的API和实现多重继承时。

28.1 接口的主要特点:

  1. 抽象方法 :接口中的所有方法默认都是抽象的(即使不加abstract关键字),在Java 8之后,可以包含默认方法和静态方法。
  2. 多重继承:Java中的类只能继承一个父类,但可以实现多个接口,这实现了多重继承的效果。
  3. 常量 :接口可以包含常量,所有的字段默认是public static final的。
  4. 隐式public :接口中的方法默认是public的,不能是privateprotected

28.2 定义和实现接口:

定义接口:
java 复制代码
public interface Animal {
    void eat();
    void sleep();
}
实现接口:
java 复制代码
public class Dog implements Animal {
    @Override
    public void eat() {
        System.out.println("Dog is eating");
    }

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

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

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

28.4 使用接口的优势:

  1. 多态性:接口可以用于实现多态,一个接口类型的引用可以指向任何实现了该接口的对象。
  2. 解耦:接口定义了一组方法的集合,具体实现由不同的类提供,这使得代码更加灵活和可维护。
  3. 代码重用:通过实现接口,不同类可以共享接口的规范,这有助于代码的重用和一致性。
  4. 分离接口和实现:接口可以定义API规范,而具体实现可以独立开发和变化,这有助于分层设计。

示例:

使用接口实现多态性:

java 复制代码
public class AnimalFeeder {
    public void feed(Animal animal) {
        animal.eat();
    }

    public static void main(String[] args) {
        AnimalFeeder feeder = new AnimalFeeder();
        Animal dog = new Dog();
        Animal cat = new Cat();
        
        feeder.feed(dog); // 输出: Dog is eating
        feeder.feed(cat); // 输出: Cat is eating
    }
}

28.5 Java 8及之后的接口特性:

  • 默认方法 :可以在接口中定义带有默认实现的方法,使用default关键字。
  • 静态方法 :可以在接口中定义静态方法,使用static关键字。
  • 私有方法(Java 9及之后):可以在接口中定义私有方法,用于辅助默认方法或静态方法。
示例:
java 复制代码
public interface Animal {
    void eat();
    void sleep();

    default void breathe() {
        System.out.println("Animal is breathing");
    }

    static void description() {
        System.out.println("This is an animal");
    }

    private void privateMethod() {
        // 仅供默认方法或静态方法调用
    }
}

28.6 多个接口的实现

  • implements说明之后用,隔开多个接口名。

28.7 总结

  • 接口在Java编程中提供了一种抽象层次,使得代码更加灵活和易于维护。通过理解和应用接口,可以设计出更具扩展性和可维护性的程序。

29. 枚举

  • enum枚举是一个特殊的"类",它表示一组常量;

  • 常量指不可更改的变量,如final定义下的变量;

  • 要创建enum,请使用enum关键字,并用逗号,分隔常量;

  • 【注意】:定义的常量名应该为大写字母

  • 与数组一样,可以使用.来访问枚举中的常量;

  • 可以在类中创建enum枚举;

  • 枚举通常用于switch语句中作为case的比较值检查相应的值;

  • 枚举类型有一个values()方法,该方法返回所有枚举常量的数组 。如果要循环遍历枚举的常量,可以用.values()先将枚举转化成数组,再使用for-each方法对其遍历输出/访问即可;

  • 枚举常量的赋值方式是常量名{常量的值,......},属性的赋值方法是常量名(属性值)

29.1 枚举属性和枚举方法

  • enum枚举可以像class一样具有属性和方法。唯一的区别是枚举常量是public static final
    在Java中,枚举(enum)是一种特殊的类,用于表示一组固定的常量。与普通类不同,枚举的实例是有限且固定的。枚举不仅可以包含常量,还可以包含属性、方法和构造函数,从而使其更加灵活和功能强大。
定义枚举的属性和方法
1. 枚举常量带有属性:

枚举常量可以带有属性,这些属性可以在构造函数中进行初始化。

  • 在Java中,枚举常量带有属性时,通常会将这些属性声明为private final并通过构造函数进行初始化,这提供了枚举属性的不可变性和封装的特点。
java 复制代码
public enum Day {
    MONDAY("Start of the work week"),
    TUESDAY("Second day"),
    WEDNESDAY("Midweek"),
    THURSDAY("Almost there"),
    FRIDAY("End of the work week"),
    SATURDAY("Weekend"),
    SUNDAY("Rest day");

    private final String description;

    // 构造函数
    Day(String description) {
        this.description = description;
    }

    // 获取描述的方法
    public String getDescription() {
        return description;
    }
}

在这个示例中,每个枚举常量都带有一个描述属性,并通过构造函数进行初始化。

2. 枚举方法:

枚举还可以包含方法,可以根据需要定义实例方法和静态方法。

java 复制代码
public enum Operation {
    ADDITION("+") {
        public double apply(double x, double y) {
            return x + y;
        }
    },
    SUBTRACTION("-") {
        public double apply(double x, double y) {
            return x - y;
        }
    },
    MULTIPLICATION("*") {
        public double apply(double x, double y) {
            return x * y;
        }
    },
    DIVISION("/") {
        public double apply(double x, double y) {
            return x / y;
        }
    };

    private final String symbol;

    Operation(String symbol) {
        this.symbol = symbol;
    }

    @Override
    public String toString() {
        return symbol;
    }

    // 抽象方法,每个枚举实例必须实现此方法
    public abstract double apply(double x, double y);
}

在这个示例中,每个枚举常量都表示一个数学运算,并实现了apply方法。

使用示例:
java 复制代码
public class EnumTest {
    public static void main(String[] args) {
        // 使用 Day 枚举
        for (Day day : Day.values()) {
            System.out.println(day + ": " + day.getDescription());
        }

        // 使用 Operation 枚举
        double x = 10.0;
        double y = 5.0;
        for (Operation op : Operation.values()) {
            System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y));
        }
    }
}

输出:

MONDAY: Start of the work week
TUESDAY: Second day
WEDNESDAY: Midweek
THURSDAY: Almost there
FRIDAY: End of the work week
SATURDAY: Weekend
SUNDAY: Rest day

10.000000 + 5.000000 = 15.000000
10.000000 - 5.000000 = 5.000000
10.000000 * 5.000000 = 50.000000
10.000000 / 5.000000 = 2.000000
关键点总结:
  1. 属性:枚举可以包含属性,并通过构造函数初始化。
  2. 方法:枚举可以包含实例方法和静态方法。
  3. 抽象方法:枚举可以定义抽象方法,每个枚举常量必须实现该方法。
  4. 构造函数 :枚举的构造函数总是私有的,可以省略private修饰符。

通过这些特性,Java的枚举类型不仅仅是简单的常量集合,还能实现复杂的行为和属性,使其在代码设计中更加灵活和强大。

30. 用户输入

  • java采用scanner类用于获取用户输入,这个类属于java.util包中;
  • 同样,为了使用scanner类,需要创建该类的对象,从而使用scanner类文档中任何可用的方法;
  • 输入类型与之对应的方法,基本名称就是next<数据类型,记得开头字母要大写>
    1. nextBoolean():从用户处读取boolean布尔值;
    2. nextByte():从用户处读取byte字节值;
    3. nextDouble():从用户处读取double双精度值;
    4. ......

31. 日期和时间

  • 与C++不同,Java没有内置的Date类,但是我们可以导入java.time包来使用Date类和time API

  • java.time包含的时间和日期类有:

    1. LocalDate:表示日期,格式是年--月--日;
    2. LocalTime:表示时间,格式是小时--分钟--秒钟--纳秒;
    3. LocalDateTime:表示日期和时间;
    4. DateTimeFormatter格式化显示日期时间;
  • now()方法可以调出当前的时间数据 ,不同的类都有其自己的now()方法;

  • 如果你想让时间按照自己喜欢的格式显示,可以用DateTimeFormatter类格式化,并用.offpattern描述自己需要的格式,并接纳;

  • 上述描述,小写的dd代表日期,大写的若干个M代表月份,yyyy象征年份。

32,数组列表

  • java.util包中,包含ArrayList类,它是一个可以调整大小的数组(array),或者说C++的向量顺序表
  • ArrayLisArray最大的区别就是可以改变大小,可以随意增加或者删除元素;
  1. 生成:

    java 复制代码
    import java.util.ArrayList; // 导入 ArrayList 类
    
    ArrayList<ElemType> <Name> = new ArrayList<ElemType>(); // 创建一个 ArrayList 对象
  2. 增加:.add(<值>)的方法,且增加在末尾

  3. 查询:.get位置索引)的方法;

  4. 修改:。set(位置索引,值)的方法;

  5. 删除:.remove(位置索引)

  6. 计算大小:.size()的方法;

  7. 遍历:for循环 + .size()方法找到数量大小 / for-each循环;

  8. 排序:在java.util包中,还有一个非常有用的类Collection。该类中的.sort()方法可用于按字母或者数字顺序列表的排序,默认是升序。当然除此之外,你还可以传递一个实现了comparator接口的实例给该方法,以自定义的顺序进行排序,如:

    java 复制代码
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    
    public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(3);
        list.add(1);
        list.add(2);
    
        // 自定义排序:降序
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1; // 降序排序
            }
        });
        System.out.println(list); // 输出: [3, 2, 1]
    }
  • 需要注意的是,ArrayList中的元素其实是对象,所以要生成对应数据类型的数组列表,使用的是基本类型,如 Integer(int的包装类)、String、Boolean(boolean的包装类)、Character(char的包装类)、Double(double的包装类);
  • 非常别扭的是,在自动装箱功能普及的时候,对ArrayList的生成依旧要指定包装类名 ,但在ArrayList以外的代码,包装类名和基本类型基本是通用的
相关推荐
职略1 小时前
负载均衡类型和算法解析
java·运维·分布式·算法·负载均衡
A22741 小时前
LeetCode 196, 73, 105
java·算法·leetcode
容若只如初见2 小时前
项目实战--Spring Boot + Minio文件切片上传下载
java·spring boot·后端
阿里巴巴P8资深技术专家2 小时前
Java常用算法&集合扩容机制分析
java·数据结构·算法
weixin_440401692 小时前
分布式锁——基于Redis分布式锁
java·数据库·spring boot·redis·分布式
码农爱java2 小时前
Spring Boot 中的监视器是什么?有什么作用?
java·spring boot·后端·面试·monitor·监视器
zengson_g3 小时前
当需要对大量数据进行排序操作时,怎样优化内存使用和性能?
java·数据库·算法·排序算法
血战灬狂龙3 小时前
pom.xml文件加载后没有变成maven图标
xml·java·maven
无名指的等待7123 小时前
SpringBoot实现图片添加水印(完整)
java·spring boot·后端
胡尚4 小时前
Ratf协议图解、Nacos CP集群源码分析
java·spring boot