JavaSE 学习笔记
学了一部分才开的个人博客并开始使用markdown写笔记,前面的笔记就不补了。
Chapter 07
可变参数
可变参数的使用:
可变参数示例:
1
2
3
4
5
6/**
* 实现多个参数求和
*/
public int sum(int... nums){
//方法体
}代码解读:
1.int… 表示接收的是可变参数,类型是int,可以接收多个int类型参数。
2.使用可变参数时,可以当作数组来使用。
3.遍历nums求和。
注意事项和使用细节:
1.可变参数的实参可以为数组。
2.可变参数的本质就是数组。
3.可变参数可以和普通类型的参数一起放在形参列表,但是需要保证可变参数在最后。
1
2
3
4
5
6/**
* 示例
*/
public void f(String str,double... nums){
//方法体
}4.一个形参列表中只能出现一个可变参数。
作用域
作用域的基本使用:
1.局部变量:一般指在成员方法中定义的变量,是除了属性之外的其他变量,作用域为定义它的代码块中。局部变量赋值后才可以使用,即无默认值。
2.全局变量:即属性,作用域为整个类体。全局变量可以不赋值,直接使用(默认值)。
注意事项和使用细节:
1.属性和局部变量可以重名,访问时遵循就近原则。
2.在同一个作用域中,两个局部变量不能重名。
3.属性生命周期较长:伴随对象;局部变量生命周期较短:伴随代码块。
4.属性不仅可以被本类使用,也可以被其他类使用(通过对象调用);局部变量只能在本类的对应方法中使用。
5.属性可以加修饰符,局部变量不可以加修饰符。
构造方法/构造器
基本语法:
[修饰符] 方法名(形参列表){
方法体;
}
说明:
1.构造器的修饰符可以默认。
2.构造器没有返回值。
3.方法名必须和类的名字一致。
4.参数列表的规则和成员方法相同。
5.构造器的调用由系统完成。
主要作用:完成对新对象的初始化。
快速入门:
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18/**
* 创建Person对象时,就直接指定这个对象的年龄和姓名
*/
public class Example{
public static void main(String[] args){
//当我们创建一个对象时,直接通过构造器指定名字和年龄
Person p1 = new Person("Smith",80);
}
}
class Person{
String name;
int age;
public Person(String pName,int pAge){
name = pName;
age = pAge;
}
}解读:
1.构造器没有返回值**(也不能返回void类型)**
注意事项和使用细节:
1.一个类可以定义多个不同的构造器,即构造器的重载。
2.构造器是完成对象的初始化的,不是创造对象。
3.创建对象时,系统自动的调用该类的构造方法。
4.如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造器)。
5.一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器,除非自己显式定义无参构造器。
无参构造器语法:
方法名(){
}
对象创建的流程分析
案例:
1 | class Person{ |
流程分析:
1.加载Person类信息(Person.class),只会加载一次。
2.在堆中分配空间(地址)。
3.完成对象初始化:
- 默认初始化。(age = 0,name = null)
- 显式初始化。(age = 90,name = null)
- 构造器的初始化。(age = 20,name = 小明)
4.将对象在堆中的地址返回给p(p是对象名,也可以理解为对象的引用)。
this关键字
this代表当前对象。
注意事项和使用细节:
1.this关键字可以用来访问本类的属性、方法、构造器。
2.this用于区分当前类的属性和局部变量。
3.this关键字访问成员方法的语法:
this.方法名(参数列表);
4.this关键字访问构造器的语法:
只能在构造器中访问另一个构造器,不可以在普通方法中使用。
this(参数列表);
该语句要使用,则必须放在构造器的第一句。
5.this不能在类定义的外部使用,只能在类定义的方法中使用。
Chapter 08
包
作用:
1.区分相同名字的类。
2.当类很多时,可以很好的管理类。
3.控制访问范围。
基本语法:
package 包名;
本质:创建不同文件夹来保存类文件。
包的命名:
1.命名规则:只能包含数字、字母、下划线、小圆点,但不能用数字开头,不能是关键字或保留字。
2.命名规范:一般是小写字母+小圆点
com.公司名.项目名.业务模块名
常用的包:
1.java.lang.*:是基本包,默认引入。
2.java.util.*:系统提供的工具包、工具类。
3.java.net.*:网络包,网络开发。
4.java.awt.*:做java的界面开发,GUI。
如何引入包:
语法:
import 包;
示例:
import java.util.Scanner; 只是引入Scanner类。
import java.util.*; 将java.util包的所有类都引入。
注意事项和使用细节:
1.package的作用是声明当前类所在的包,需要放在class的最上面,一个类中最多只有一句package。
2.import指令放在package下面,在类定义前面,可以有多句且没有顺序要求。
访问修饰符
基本介绍:用于控制方法和属性(成员变量)的访问权限(范围)。
1.公开级别:用
public
修饰,对外公开。2.受保护级别:用
protected
修饰,对子类和同一个包中的类公开。3.默认级别:没有修饰符号,向同一个包的类公开。
4.私有级别:用
private
修饰,只有类本身可以访问,不对外公开。4种访问修饰符的访问范围:
访问级别 访问控制修饰符 同类 同包 子类 不同包 公开 public √ √ √ √ 受保护 protected √ √ √ × 默认 没有修饰符 √ √ × × 私有 private √ × × × 使用的注意事项:
1.修饰符可以用来修饰类中的属性、成员方法以及类。
2.只有默认和public才能修饰类,并且遵守上述访问权限的特点。
3.成员方法的访问规则和属性完全一样。
封装
优点:
1.隐藏实现细节。
2.可以对数据进行验证,保证安全合理。
封装实现的步骤:
1.将属性进行私有化**(不能直接修改属性)**。
2.提供一个公共的set方法,用于对属性判断并赋值。
如果使用构造器且需要验证属性,则可以在构造器中使用set方法。
public void setXxx(类型 参数名){ //Xxx表示某个属性
//加入数据验证的业务逻辑
属性 = 参数名;
}
3.提供一个公共的get方法,用于获取属性的值。
public XX getXxx{ //权限判断
return xx;
}
继承
基本介绍:
继承可以解决代码复用。当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类(基类)。在父类(基类)中定义这些相同的属性和方法,所有的子类(派生类)不需要重新定义这些属性和方法,只需要通过extends来声明继承父类(基类)即可。
基本语法:
class 子类 extends 父类{
}
注意事项和使用细节:
1.子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问(可以间接访问),要通过父类提供公共的方法(get方法)去访问。
2.子类必须调用父类的构造器,完成父类的初始化。
3.当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器。如果父类没有提供无参构造器,则必须在子类的构造器中用
super(参数列表)
去指定使用父类的哪个构造器完成对父类的初始化工作,否则编译不会通过。4.如果希望指定去调用父类的某个构造器,则显式调用
super()
。5.super在使用时,必须放在构造器第一行。(super只能在构造器中使用)
6.
super()
和this()
都只能放在构造器第一行,因此这两个方法不能共存在一个构造器中。7.Java所有类都是Object类的子类。
8.父类构造器的调用不限于直接父类,将一直往上追溯直到Object类。
9.子类最多只能直接继承一个父类,即Java中是单继承机制。
10.不能滥用继承,子类和父类之间必须满足
is-a
的逻辑关系。本质分析:按照查找关系来返回信息
1.首先看子类是否有该属性。
2.如果子类有这个属性,并且可以访问,则返回信息;如果子类没有这个属性,则看父类有没有这个属性(如果父类有该属性,并且可以访问,则返回信息)。
3.如果父类没有该属性,则按照
2
的规则,继续找上级父类,直到Object类。如果在查找过程中找到了该属性,但是无法访问,则直接报错。
super关键字
基本介绍:
super代表父类的引用,用于访问父类的属性、方法、构造器。
基本语法:
1.访问父类的属性,但不能访问父类的private属性。
super.属性名;
2.访问父类的方法,不能访问父类的private方法。
super.方法名(参数列表);
3.访问父类的构造器(只能放在构造器的第一句)。
super(参数列表);
注意事项和使用细节:
1.当子类中有和父类中成员(属性和方法)重名时,为了访问父类的成员,必须通过
super
。如果没有重名,使用super
(直接查找父类)、this
(先查找本类)、直接访问是一样的。2.super的访问不限于直接父类,如果间接父类和本类中有同名的成员,也可以用super去访问间接父类的成员。如果多个基类中都有同名成员,使用super访问时,遵循就近原则。(也要遵守访问权限的相关规则)
super和this的比较
区别点 | this | super |
---|---|---|
访问属性 | 访问本类中的属性,如果本类没有此属性,则从父类中继续查找。 | 访问父类中的属性。 |
调用方法 | 访问本类中的方法,如果本类没有此方法,则从父类中继续查找。 | 直接访问父类中的方法。 |
调用构造器 | 调用本类构造器,必须放在构造器的首行。 | 调用父类构造器,必须放在子类构造器的首行。 |
特殊 | 表示当前对象。 | 子类中访问父类对象。 |
方法重写/覆盖
子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的那个方法。
注意事项和使用细节:
1.子类的方法的形参列表、方法名称要和父类方法的形参列表、方法名称完全一样。
2.子类方法的返回类型和父类方法的返回类型一样,或者是父类返回类型的子类。
3.子类方法不能缩小父类方法的访问权限(可以扩大)。
方法重写和重载的比较
名称 | 发生范围 | 方法名 | 形参列表 | 返回类型 | 修饰符 |
---|---|---|---|---|---|
重载(overload) | 本类 | 必须一样 | 类型、个数或者顺序,至少有一个不同 | 无要求 | 无要求 |
重写(override) | 父、子类 | 必须一样 | 必须相同 | 子类重写的方法返回的类型和父类返回的类型一致,或者是其子类 | 子类方法不能缩小父类方法的访问范围 |
多态
基本介绍:
方法或对象具有多种形态,建立在封装和继承的基础之上。
具体体现:
1.方法的多态。(重写和重载均体现多态)
2.对象的多态。
- 一个对象的编译类型和运行类型可以不一致。
- 编译类型在定义对象时就确定了,不能改变。
- 运行类型是可以变化的。
- 编译类型看定义时
=
的左边,运行类型看=
的右边。
多态的向上转型:
1.本质:父类的引用指向了子类的对象。
2.语法:
父类类型 引用名 = new 子类类型();
3.特点:
编译类型看左边,运行类型看右边。
可以调用父类中的所有成员(需遵循访问权限)。
不能调用子类中的特有成员。
在编译阶段,能调用哪些成员是由编译类型来决定的。
最终运行效果看子类(运行类型)的具体实现,即调用方法时,按照从子类开始查找方法(根据运行类型),然后调用,规则与方法调用规则一致。
多态的向下转型:
1.语法:
子类类型 引用名 = (子类类型) 父类引用;
2.特点:
- 只能强转父类的引用,不能强转父类的对象。
- 要求父类的引用必须指向的是当前目标类型的对象。
- 当向下转型后,可以调用子类类型中所有的成员。
多态的注意事项和细节讨论:
1.属性没有重写之说,属性的值看编译类型。
2.
instanceof
比较操作符,用于判断对象的运行类型是否为XX类型或XX类型的子类型。动态绑定机制
1.当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定。
2.当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用。
多态的应用
多态数组
- 数组的定义类型为父类类型,里面保存的实际元素类型为子类类型。
- 使用向下转型。
多态参数
- 方法定义的形参类型为父类,实参类型允许为子类。
Object类详解
equals方法
equals
和==
的对比
1.==
是比较运算符。既可以判断基本类型,又可以判断引用类型。如果判断基本类型,则判断的是值是否相等;如果判断引用类型,则判断的是地址是否相等(即判定是不是同一个对象)。
2.equals
是Object
类中的方法,只能判断引用类型。默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等。
hashcode方法
- 小结:
1.提高具有哈希结构的容器的效率。
2.两个引用,如果指向的是同一个对象,则哈希值一定相同;如果指向的是不同对象,则哈希值不相同。
3.哈希值主要根据地址号来的,完全将哈希值等价于地址。
toString方法
- 基本介绍:
默认返回全类名(包名+类名) + @ + 哈希值的十六进制
,子类往往重写toString方法,用于返回对象的属性信息。 - 重写
toString
方法打印对象或拼接对象时,都会自动调用对象的toString形式。 - 当直接输出一个对象时,toString方法会被默认地调用。
finalize方法
- 当对象被回收时,系统自动调用该对象的
finalize
方法。子类可以重写该方法,做一些释放资源的操作。 - 什么时候被回收:当某个对象没有任何引用时,则jvm就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象。在销毁该对象前,会先调用finalize方法。
- 垃圾回收机制的调用由系统来决定(即由自己的GC),也可以通过
System.gc()
主动触法垃圾回收机制。
断点调试debug
- 在断点调试过程中,是运行状态,是以对象的运行类型来执行的。
- 断点调试是指在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住。然后可以一步一步往下调试,调试过程中可以看各个变量的当前值,出错的话,调试到出错的代码行即显示错误,停下。进行分析从而找到这个bug。
断点调试快捷键
按键 | 内容 |
---|---|
F7 |
跳入方法内 |
F8 |
逐行执行代码 |
Shift+F8 |
跳出方法 |
F9 |
resume,执行到下一个断点 |
- 将光标放在某个变量上,可以看到最新的数据。
- 可以在debug过程中动态的下断点。
Chapter 10
类变量/静态变量
类变量(静态变量/静态属性)是该类所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量。
- 类变量时对着类的加载而创建,所以即使没有创建对象实例也可以访问。
- 类变量的生命周期是随类的加载开始,随着类消亡而销毁。
定义语法
(1)访问修饰符 static 数据类型 变量名; (推荐)
(2)static 访问修饰符 数据类型 变量名;
访问方法
(1)类名.类变量名 (推荐)
(2)对象名.类变量名
- 类变量的访问必须遵循访问权限。
类方法/静态方法
定义语法
(1)访问修饰符 static 数据返回类型 方法名(){} (推荐)
(2)static 访问修饰符 数据返回类型 方法名(){}
调用
(1)类名.类方法名
(2)对象名.类方法名
使用场景
当方法中不涉及到任何和对象相关的成员,则可以将方法设计成静态方法,提高开发效率。
注意事项和细节讨论
- 类方法和普通方法都是随着类的加载而加载,将结构信息储存在方法区。类方法中无this的参数,普通方法中隐含着this的参数。
- 类方法可以通过类名调用,也可以通过对象名调用。
- 普通方法和对象有关,需要通过对象名调用,不能通过类名调用。
- 类方法中不允许使用和对象有关的关键字,比如
this
、super
,普通方法(成员方法)可以。 - 类方法中只能访问静态变量和静态方法。
- 普通成员方法既可以访问非静态变量(/方法),也可以访问静态变量(/方法)。
理解main方法语法
- main方法是由虚拟机调用。
- Java虚拟机需要调用类的mian()方法,所以该方法的访问权限必须是public。
- Java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static。
- 该方法接收String类型的数组参数,该数组中保存执行Java命令时传递给所运行的类的参数。
特别提示
在main()方法中,我们可以直接调用main方法所在类的静态方法或静态属性。但是,不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员。
代码块
基本介绍
代码化块又称为初始化块,属于类中的成员**(是类的一部分)。类似于方法,将逻辑语句封装在方法体中,通过{}包围起来。
但代码块没有方法名,没有返回,没有参数,只有方法体**,而且不用通过对象或类显示调用,而是在加载类或创建对象时隐式调用。
代码块的调用优先于构造器。
基本语法
[修饰符]{
代码
};
注意:
- “修饰符”可选,如果要写只能写static。
- 代码块分为两类,使用static修饰的叫静态代码块,没有static修饰的叫普通代码块/非静态代码块。
- 逻辑语句可以为任何逻辑语句。
;
可以写上,也可以省略。
好处
- 相当于另一种形式的构造器(对构造器的补充机制),可以做初始化的操作。
- 如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性。
使用注意事项和细节讨论
- static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行。并且只会执行一次。如果是普通代码块,每创建一个对象就执行。
- 类什么时候被加载:
- 创建对象实例时。
- 创建子类对象实例,父类也会被加载。
- 使用类的静态成员时(静态属性、静态方法)。
- 普通的代码块在创建实例时,会被隐式的调用,被创建一次就被调用一次。如果只是使用类的静态成员时,普通代码块并不会执行。
- 创建一个对象时,在一个类调用顺序是:
1.调用静态代码块和静态属性初始化。(注意:静态代码块和静态属性初始化调用的优先级一样。如果有多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用。)
2.调用普通代码块和普通属性的初始化。(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,则按定义顺序调用。)
3.调用构造方法。 - 构造方法(构造器)的最前面其实隐含了
super()
和调用普通代码块。 - 创建一个子类时(继承关系),他们的静态代码块、静待属性初始化、普通代码块、普通属性初始化、构造方法的调用顺序如下:
1.父类的静态代码块和静态属性(优先级一样,按定义顺序执行)。
2.子类的静态代码块和静态属性(优先级一样,按定义顺序执行)。
3.父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)。
4.父类的构造方法。
5.子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)。
6.子类的构造方法。 - 静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员。