Java
注释
単行注释
格式 //注释信息
多行注释
格式 /*注释信息*/
文档注释
格式 /**注释信息*/
关键字
class关键字
用于(创建/定义)应该类,类是Java最基本的组成单元
字面量
制表符
\t 在打印时,把前面字符串长度补齐到8或者8的整数倍,最少一个空格,最多8个空格
变量名
int 整数类型
**byte **
short
long 定义时,数据值要加一个L作为后缀.可以大写也可以小写
double 小数类型
float 定义时,数据值要加一个F作为后缀
char 字符类型
String 字符串类型 注:S要大写
boolean 布尔类型
使用方法
注意事项
1.只能存一个值
2.变量名不允许重复定义
3.一条语句可以定义多个变量
int a=1,b=2,c=3;
4.变量在使用之前要进行赋值
5.变量要注意作用域范围
标识符
输入
Scanner,这个类可以接受键盘输入的数字
导包,要写在类定义的上面
1 | //1 |
运算符
数值相加
如果在计算时有小数参与,结果可能会不准确
算数语法跟c语言一样
数字进行运算时,数据类型不一样不能运算,需要转成一样的,才能运算
隐式转换:取值范围小的数值–>取值范围大的数值
强制转换:取值范围大的数值–>取值范围小的数值
字符串相加
字符串的“+”操作,跟python差不多
字符相加
自增、自减
跟c差不多
赋值运算符
+=、-=、/==等等 ,跟c一样
逻辑运算符
&、 |、 ^ 、!
&&、|| 当左边的表达式能确定最终的结果时,右边就不会参与运行了
三元运算符
a?b:c 、; 跟c差不多
优先级
判断语句
if语句
跟c一样
switch语句
在jdk12时,可以使用
1 | switch(a) |
循环语句
跟c一样有for,while,do…while
数组
定义方式
1 | 格式一 |
注意:不同的数据类型对应不同的默认值
- 整数类型:0
- 小数类型:0.0
- 布尔类型:false
- 字符类型:‘\u0000’
- 引用类型:null
数组的初始化
1 | 格式一 |
数组的地址值
1 | int arr[]={1,2,3,4,5,6,7,8,9,10}; |
[I@14ae5a5
解读:
[ 表示是数组.
i 表示是int类型
@ 表示一个间隔符号(固定格式)
14ae5a5 数组真正的地址值(十六进制)
通常把这个整体统称为地址
数组的遍历
1 | 第一种 fro循环遍历 |
1 | 第二种 |
1 | 第三种 foreach语句遍历 |
java内存分配
栈 方法运行时使用的内存,比如main方法运行,进入方法栈中执行
堆 存储对象或者数组,new来创建的,都存储在堆内存中
方法区 存储可以运行的class文件
本地方法栈 JVM在使用操作系统功能的时候使用,和我们开发无关
寄存器 给cpu使用 ,和我们开发无关
方法
方法的定义
程序中最小的执行单元
方法的格式
最简单的格式
1 | public static void 方法名(){ |
带参数的格式
有实参和形参的区别
1 | public static void 方法名(int num1, int num2){ |
带返回值的格式
1 | public static 返回值类型 方法名(参数){ |
方法的重载
在同一个类中,定义了多个同名的方法,这些同名的方法具有同种的功能。
每个方法具有不同的参数类型或参数个数,这些同名的方法,就构成了重载关系
注意,一个变量不构成重载关系
方法的基本数据型和引用数据类型
修饰符
在 Java 中,修饰符(Modifiers)用于控制类、方法、变量的访问权限、行为以及其他特性。修饰符分为两大类:访问修饰符 和 非访问修饰符。修饰符提供了对类、方法、属性等的访问控制、功能增强以及其他特性管理。
访问修饰符
访问修饰符用于定义类、方法、变量的访问范围,即控制哪些类、方法、变量可以被访问。Java 提供了四种访问修饰符:
public
- 含义:表示该成员可以被任何其他类访问。
- 适用范围:类、方法、变量。
1 | public class MyClass { |
private
- 含义:表示该成员只能在定义它的类内部访问,不能在类外部访问。
- 适用范围:方法、变量。
1 | class MyClass { |
protected
- 含义:表示该成员可以在同一包中的其他类访问,也可以在不同包中通过继承访问。
- 适用范围:方法、变量。
1 | class MyClass { |
默认
- 含义:如果没有指定访问修饰符,默认是包私有,表示该成员仅能在同一包内的类中访问,包外不可访问。
- 适用范围:方法、变量。
1 | class MyClass { |
面向对象
类和对象
类:是对象共同特征的描述.
对象:是真实存在的东西
在JAVA中必须先设计类,才能获得对象
1 | public class 类名{ |
测试类、javaBean类和工具类
- 测试类(Test Class)
测试类通常用于单元测试(Unit Testing)。它的目的是验证你的代码是否按预期工作。Java 中有一些常用的测试框架,如 JUnit、TestNG 等,它们帮助你创建和运行测试。
特点:
- 包含测试方法,通常以
@Test
注解标注。 - 每个测试方法通常是独立的,验证特定功能或方法。
- 测试类不用于业务逻辑实现,而是用于验证程序的正确性。
例子:
1 | import org.junit.jupiter.api.Test; |
在上面的代码中,CalculatorTest
类是一个测试类,testAdd()
是一个测试方法,它验证 Calculator
类中的 add()
方法是否正确。
JavaBean 是一种符合特定规范的 Java 类,它通常用于数据封装。JavaBean 类的主要目的是通过提供一组 getter 和 setter 方法,使得它可以作为一个数据传输对象(DTO)在应用程序中传递数据。
特点:
- JavaBean 必须有一个无参构造函数。
- 类中的成员变量通常是私有的(
private
),通过公共的 getter 和 setter 方法访问。 - 它应该实现
Serializable
接口,以便可以进行序列化。 - 常用于数据库的实体映射或网络传输。
例子:
1 | public class User implements java.io.Serializable { |
在这个例子中,User
类是一个 JavaBean 类,包含了私有成员变量 name
和 age
,以及它们的 getter 和 setter 方法。这个类符合 JavaBean 的规范,通常用于传递用户信息。
工具类是一个包含一组静态方法的类,这些方法提供常用的功能,通常与某些操作或计算相关。工具类中的方法通常是通用的,因此可以在应用程序的不同部分重复使用。工具类通常只包含静态方法,并且不需要实例化。
特点:
- 工具类通常只包含静态方法,方便调用。
- 通常不需要实例化对象。
- 可以包含各种实用功能,如字符串处理、日期处理、数学计算等。
例子:
1 | public class StringUtils { |
在上面的 StringUtils
类中,isEmpty()
和 reverse()
方法是工具方法。你可以直接调用这些静态方法而不需要创建 StringUtils
的实例。
主要区别总结:
- 测试类:用于测试应用程序的代码是否按预期工作,通常包含测试框架(如 JUnit)的测试方法。
- JavaBean 类:用于封装数据,通常包含私有字段和公共的 getter/setter 方法,符合 JavaBean 的规范。
- 工具类:包含常用的静态方法,用于实现通用功能(如字符串处理、文件操作等),通常不需要实例化。
如何得到类的对象
1 | 类名 对象名=new 类名(); |
类的封装
对象代表什么,就得封装对应的数据,并提供数据对应的行为
跟python导入的模块一样,可以用来处理数据
this关键字
this用来调用成员变量,区分成员变量和局部变量
1 |
|
构造方法
作用:在创建对象的时候给成员变量进行赋值
无参数构造方法: 初始化的对象时,成员变量的数据均采用默认值,
有参数构造方法: 在初始化对象的时候,同时可以为对象进行赋值。
形式
1 | public class Student{ |
特点:
1.方法名与类名相同,大小写也要一致
2.没有返回类型,连void也没有
3.没有具体的返回值(不能由retrun带回结果数据)
执行时机:
1.创建对象的时候由虚拟机调用,不能手动调用构造方法
2.每创建一次对象,就会调用一次构造方法
注意事项
① 构造方法的定义
如果没有定义构造方法,系统将给出一个默认的无参数构造方法
如果定义了构造方法,系统将不再提供默认的构造方法
② 构造方法的重载
带参构造方法,和无参数构造方法,两者方法名相同,但是参数不同,这叫做构造方法的重载
③ 推荐的使用方式
无论是否使用,都手动书写无参数构造方法,和带全部参数的构造方法
标准JavaBean
- 类名需要见名知意
- 成员变量使用private修饰
- 提供至少两个构造方法
- 无参构造方法
- 带全部参数的构造方法
- 成员方法
提供每一个成员变量对应的setXxx()/getXxx()
如果还有其他行为,也需要写上
static
static表示静态,是Java中的一个修饰符,可以修饰成员方法和成员变量
被static修饰的成员变量叫做静态变量(类变量)
被static修饰的成员方法,叫做静态方法
注意事项
类的继承
Java中提供一个关键字extends,用这个关键字,我们可以让一个类和你应该类建立起继承关系
1 | public class Student extends Person {} |
student成为子类(派生类),Person成为父类(基类或超类)
1 | // 父类 |
使用继承的好处
可以把多个子类中重复的代码抽取到父类中了,提高代码的复用性
子类可以在父类的基础上,增加其他的功能,使子类更强大,
使用条件
当类与类之间,存在相同(共性)的内容,并满足子类是父类的一种,就可以考虑使用继承,来优化代码
继承的特点
Java只支持但继承,不支持多继承,但支持多层继承
多层继承:子类A可以继承父类B,父类B可以继承父类C
每一个类都直接或者间接的继承于Object
子类能继承父类的内容
成员变量和成员方法访问特点
遵循就近原则:谁离我近,我就用谁
1 | class Parent { |
如果出现了重名变量
1 | class Parent { |
方法重写注意事项和要求
注意:子类中重写的方法上面要加上@override
构造方法的访问特点
继承中:构造方法的访问特点
父类中的构造方法不会被子类继承。
子类中所有的构造方法默认先访问父类中的无参构造,再执行自己
为什么?
子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据
子类初始化之前,一定要调用父类构造方法先完成父类数据空间的初始化。
使用this()访问本类的构造方法
使用super访问父类的构造方法
this、super总结
this : 理解为一个变量,表示当前方法调用者的地址值
super: 代表父类存储空间
类的多态
对象代表什么,就得封装对应的数据,并提供数据对应的行为
定义
同类型的对象,表现出不同形态
多态表现形式
父类类型 对象名称 = 子类对象
多态的前提
- 有继承关系
- 有父引用指向子类对象
- 有方法重写
多态调用成员特点
变量调用:编译看左边,运行也看左边
方法调用:编译看左边,运行看右边
变量调用
编译看左边:javac编译代码的时候,会看左边的父类中有没有这个变量,如果有,编译成功,如果没有编译失败。
在Java中,编译时的行为是由引用变量的类型(也就是“左边”)决定的。Java编译器在编译代码时,确定方法调用或成员访问是根据引用类型来进行检查的。因此,编译时检查的是引用变量所声明的类型,而不是它实际指向的对象类型。
1 | class Parent { |
编译时:在上面的代码中,obj
是Parent
类型的引用,而不是Child
类型。因此,编译器会检查Parent
类中是否有名为x
的变量,虽然obj
在运行时指向Child
对象,但编译器只会检查Parent
类中的x
,因此无法找到x
变量,编译器会报错。如果我们使用obj.x
,编译器就无法知道它是否在Child
类中有x
字段,它只会根据Parent
类的声明进行检查。
运行也看左边:java运行代码的时候,实际获取的就是左边父类中成员变量的值
在运行时,Java会根据实际对象的类型来决定使用哪个成员变量或方法。这是Java中动态绑定的特性(尤其是方法的动态绑定)。对于成员变量(尤其是实例变量),它会选择实际对象中的值,即使引用类型是父类类型,也会访问实际对象中(子类)的成员变量。
1 | class Parent { |
运行时:虽然obj
是Parent
类型的引用,但它指向的是Child
类型的对象。obj.x
访问的是Parent
类中的x
变量,因为编译器在编译时是根据obj
的声明类型Parent
来查找成员变量的,而不是Child
类的成员变量。
方法调用
1 | class Animal { |
- 编译时看左边:
- 在编译时,
obj
的引用类型是Animal
,所以编译器会检查Animal
类中是否有sound()
方法。 - 编译器会发现
Animal
类有sound()
方法,因此不会报编译错误。
- 运行时看右边:
- 运行时,
obj
指向的是Dog
类的对象。因此,Java会根据实际对象的类型(Dog
)来调用重写后的Dog
类中的sound()
方法。 - 尽管引用类型是
Animal
,运行时仍然会调用子类Dog
的sound()
方法,输出的是Dog barks
,而不是Animal makes a sound
。
多态的优势和弊端
抽象类和抽象方法
类用于描述现实生活中一类事物。类中有属性、方法等成员。
父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有 意义,而方法主体则没有存在的意义了。
某种情况下,父类只能知道子类应该具备一个怎样的方法,但是不能够明确知道如何实现该方法。只能在子类中才能确定如何去实现方法体。例如:所有几何图形都应该具备一个计算面积的方法。但是不同的几何图形计算面积的方式不同。
我们把没有方法主体的方法称为抽象方法。Java语法规定,包含抽象方法 的类就是抽象类。
抽象方法
抽象方法 : 只有方法的声明,没有方法体,以分号 ; 结尾,使用 abstract
关键字修饰
定义格式:
1 | 修饰符 abstract 返回值类型 方法名(参数列表); |
代码举例:
1 | public abstract void run(); |
抽象方法不能用private、final、static、native修饰
抽象类
抽象类:包含抽象方法的类。如果一个类包含抽象方法,那么该类必须是抽象类,使用 abstract
关键字修饰
定义格式:
1 | public abstract class 类名 { |
代码举例:
1 | public abstract class Person { |
抽象类的使用
抽象类不能实例化,不能直接创建对象。抽象类是用来被继承的,继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类也必须声明为抽象类,使用 abstract
关键字修饰
抽象类也是类,因此原来类中可以有的成员,抽象类都可以有,那么抽象类不能直接创建对象,为什么还有构造器呢?供子类调用,子类创建对象时,需要为从父类继承的属性初始化。
抽象类不能使用final修饰
1 | public class Teacher extends Person { |
此时的方法重写,是对子类对父类抽象方法的完成实现,我们将这种方法重写的操作,叫做实现方法
实现:去掉abstract关键字,加上方法体{…}
抽象类注意事项:
抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
抽象类中,可以有成员变量。
理解:子类的共性的成员变量 , 可以定义在抽象父类中。
抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
理解:未包含抽象方法的抽象类,声明为抽象类目的就是不想让使用者创建该类的对象,通常用于某些特殊的类结构设计。
抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译报错。除非该子类也是抽象类。
理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。
接口
在抽象类中,抽象方法本质上是定义接口规范:即规定高层类的接口,从而保证所有子类都有相同的接口实现,这样,多态就能发挥出威力。
如果一个抽象类没有字段,所有方法全部都是抽象方法:
1 | abstract class Person { |
就可以把该抽象类改写为接口:interface
。
在Java中,使用interface
可以声明一个接口:
1 | interface Person { |
所谓interface
,就是比抽象类还要抽象的纯抽象接口,因为它连字段都不能有。因为接口定义的所有方法默认都是public abstract
的,所以这两个修饰符不需要写出来(写不写效果都一样)。
当一个具体的class
去实现一个interface
时,需要使用implements
关键字。举个例子:
1 | class Student implements Person { |
我们知道,在Java中,一个类只能继承自另一个类,不能从多个类继承。但是,一个类可以实现多个interface
,例如:
1 | class Student implements Person, Hello { // 实现了两个interface |
术语
注意区分术语:
Java的接口特指interface
的定义,表示一个接口类型和一组方法签名,而编程接口泛指接口规范,如方法签名,数据格式,网络协议等。
抽象类和接口的对比如下:
abstract class | interface | |
---|---|---|
继承 | 只能extends一个class | 可以implements多个interface |
字段 | 可以定义实例字段 | 不能定义实例字段 |
抽象方法 | 可以定义抽象方法 | 可以定义抽象方法 |
非抽象方法 | 可以定义非抽象方法 | 可以定义default方法 |
接口继承
一个interface
可以继承自另一个interface
。interface
继承自interface
使用extends
,它相当于扩展了接口的方法。例如:
1 | interface Hello { |
此时,Person
接口继承自Hello
接口,因此,Person
接口现在实际上有3个抽象方法签名,其中一个来自继承的Hello
接口。
继承关系
合理设计interface
和abstract class
的继承关系,可以充分复用代码。一般来说,公共逻辑适合放在abstract class
中,具体逻辑放到各个子类,而接口层次代表抽象程度。可以参考Java的集合类定义的一组接口、抽象类以及具体子类的继承关系:
1 | ┌───────────────┐ |
在使用的时候,实例化的对象永远只能是某个具体的子类,但总是通过接口去引用它,因为接口比抽象类更抽象:
1 | List list = new ArrayList(); // 用List接口引用具体子类的实例 |
default方法
在接口中,可以定义default
方法。例如,把Person
接口的run()
方法改为default
方法:
1 | // interface |
实现类可以不必覆写default
方法。default
方法的目的是,当我们需要给接口新增一个方法时,会涉及到修改全部子类。如果新增的是default
方法,那么子类就不必全部修改,只需要在需要覆写的地方去覆写新增方法。
default
方法和抽象类的普通方法是有所不同的。因为interface
没有字段,default
方法无法访问字段,而抽象类的普通方法可以访问实例字段。
字符串&API
API
简单理解:API就是别人已经写好的东西,我们不需要自己编写,直接使用即可
可通过API帮助文档查找需要的API
String
java.lang.String 类代表字符串,Java 程序中的所有字符串文字(例如“abc”)都为此类的对象。
1 | String name ="小面"; |
用+可以拼接
字符串的比较
方法(一般用这个)
1 | string1.equals(string2) 完全一样才是true,否则为false |
StringBuilder
StringBuilder 可以看成是一个容器,创建之后里面的内容是可变的
作用:提高字符串的操作效率
它与String
的主要区别在于,String
对象是不可变的,每次对String
进行修改都会生成新的字符串对象;而StringBuilder
可以直接在原对象上修改内容,避免创建新的对象,从而提高效率。
构造方法
1 | StringBuilder aa = new StringBuilder("abc"); 将abc放入StringBuilder对象里 |
常用操作
append() 添加数据,并返回对象本身
reverse() 翻转容器中的内容
length() 返回长度
toString() 实现吧StringBuilder转换为String
1 | StringBuilder aa = new StringBuilder(); |
StringJoiner
Stringloiner跟StringBuilder一样,也可以看成是一个容器,创建之后里面的内容是可变的。
通常用于将多个字符串以指定分隔符连接成一个单一的字符串
作用:提高字符串的操作效率,而且代码编写特别简洁,但是目前市场上很少有人用。
1 | StringJoiner("间隔符", "开始符号", "结束符号"); |
常用操作
add()
length()
toString()
集合
集合中可以存引用数据类型和基本数据类型,但存放基本数据类型时,要使用对应的包装类
基本数据类型 | 包装类 |
---|---|
boolean |
Boolean |
byte |
Byte |
char |
Character |
short |
Short |
int |
Integer |
long |
Long |
float |
Float |
double |
Double |
与数组的区别
数组:数组的大小是固定的,一旦定义,就无法更改。在创建数组时,必须指定其长度,并且一旦数组创建完成,大小就不能再修改。
1 |
|
集合:集合的大小是动态的,可以根据需要自动增长或缩小。例如,ArrayList
可以根据添加或删除元素自动调整大小。
1 | ArrayList<Integer> list = new ArrayList<>(); |
创建集合的对象
1 |
|
成员方法