JavaSE基础知识点总结
文章目录
- JavaSE基础知识点总结
- 1.终端的使用
- 2. jdk、jre、jvm之间的关系和各自作用
- 3.Hello World!
- 4. 数据类型
- 5.关键字与标识符
- 6.常量,常量的定义
- 7.实操一下,使用Scanner输入一个数字,然后输出
- 8.算术运算符
- 9.逻辑运算符
- 10.字符串的拼接有哪些方式?
- 11.Java三种注释方式
- 12.switch
- 13.循环中的跳转语句
- 14.数组
- 15.如何理解类与对象的关系,请举例说明
- 16.方法
- 17.自定义类
- 18.成员变量与局部变量的区别
- 19.重载
- 20.构造方法
- 21.static
- 22.继承
- 23.super关键字
- 24.this的简单运用
- 25.重写
- 26.多态
- 27.封装的概述:(重要)
- 28.抽象类
- 29.接口
- 30.Final的使用
- 31.匿名对象
- 32.内部类
- 33.枚举
- 34.包(了解)
- 35.权限修饰符
- 36.ArrayList的简单使用
- 37.接口与适配器的区别:
- 38.Java随机数
- 39.==和equal的联系与区别:
- 40.线程的五种状态
1.终端的使用
打开方式: win+r–cmd–回车
java命令:
-
javac:编译。
javac 文件名.java
-
java :执行。
java 类名
-
如果类名前无public,文件名和类名可以不一致。但加public后一定要保持类名和文件名的一致
常见的dos命令:
- d :回车,盘符切换
- dir (directory) :列出当前目录下的文件以及文件夹
- md (make directory) :创建目录
- rd (remove directory) : 删除目录
- cd (change directory) :改变指定目录(进入指定目录)
- cd… :退回到上一级目录
- cd\ : 退回到根目录
- del (delete) :删除文件,删除一堆后缀名一样的文件 *.txt
- exit :退出dos命令行
- cls (clear screen) :清屏
2. jdk、jre、jvm之间的关系和各自作用
JDK(Java Development Kit)
- JDK是Java开发工具包,是Java开发人员用来开发Java应用程序的核心工具。
- JDK包括了Java编译器(javac)、Java运行时环境(JRE)、Java类库(Java API)、调试器(JDB)等开发工具。
- JDK是完整的Java开发工具包,其中包含了JRE,因此可以用于编译、运行和调试Java程序。
JRE(Java Runtime Environment)
- JRE是Java运行时环境,是用户在运行Java程序时所需的环境。
- JRE包括Java虚拟机(JVM)和Java类库,以及其他运行Java程序所需的支持文件和库。
- JRE提供了Java程序的运行时支持,但不包括开发工具。
JVM(Java Virtual Machin)
- JVM是Java虚拟机,是Java程序运行的核心组件。
- JVM负责将Java字节码转换为特定平台上的机器代码,并管理程序的运行。
- JVM提供了内存管理、垃圾回收、线程管理等功能,使得Java程序能够在不同的操作系统和硬件平台上运行。
简而言之,JDK是用于开发Java程序的工具包,包括了编译器、运行时环境和其他开发工具;JRE是用于运行Java程序的环境,包括了Java虚拟机和类库;而JVM则是在运行时实际执行Java程序的虚拟机。三者之间的关系是:JDK包含JRE,JRE包含JVM。
3.Hello World!
打开记事本编写HelloWorld程序,黑窗口(终端)运行。
4. 数据类型
基本数据类型有哪些?
四类八种:
- 整数(byte、short、int、long)
- 小数(float、double)
- 字符类型(char)
- 布尔类型(boolean)
基本数据类型是Java语言中内置的类型
引用数据类型有哪些?
String,类,数组,接口
引用数据类型是强大的数据类型,它是基于基本数据类型创建的。JavaSE中提供了一个超级类库,类库中包含了近万种引用数据类型。
数据类型转换
类型转换顺序
byte–short–char–int–long–float–double
自动类型转换和强制类型转换区别
- 自动类型转换:小转大
- 强制类型转换:大转小(会有精度损失)
5.关键字与标识符
- 什么是标识符?
- 用来给类,对象,方法,接口等命名
- 标识符可以由那些组成?
- 英文大小写字母,数字,下划线,$
- 汉字可以是标识符吗?
- (可以)
- 能不能以数字开头?
- (不可以)
- 标识符可不可以是关键字和保留字?
- (不可以)
注意:数字不能开头,不能使用关键字,严格区分大小写,起名时见名知意
(1)包名:多单词组成时所有字母均小写,使用.连接 aaa.bbb.ccc
(2) 类名&接口名:大驼峰式 AaaBbbCcc
(3) 变量名&方法名:小驼峰式 aaaBbbCcc
(4)常量名:多单词组成是所有字母均大写,使用_连接 AAA_BBB_CCC
6.常量,常量的定义
- 整形常量默认是int类型
- 小数常量默认是double类型
- 定义长整形数据如果值超过int取值范围后面要+“L”
- 定义float类型的数据后面要+“f” 否则默认是double
7.实操一下,使用Scanner输入一个数字,然后输出
Scanner类的使用
a: 导包
import java.util.Scanner;
b:创建键盘录入对象
Scanner sc = new Scanner(System.in);
c: 读取键盘录入的一个整数
int enterNumber = sc.nextInt();
d: 读取键盘录入的字符串
String enterString = sc.next();
8.算术运算符
- ++i i++ --i i-- % /
- a+=2的原始式子:a=a+2;
- 题:2.5+5/2+3.14+6%4
- 三元运算符:a>b?a:b
- 格式: (条件表达式)?表达式1:表达式2;
- 问题1:String result = (a==b) ? “相等” : “不相等”;
- 问题2:int n = (3>2 && 4>6) ? 100 : 200;
9.逻辑运算符
运算符 | 运算规则 | 范例 | 结果 |
---|---|---|---|
& | 与 | false&true | false |
| | 或 | false|true | true |
^ | 异或 | true^false | true |
! | 非 | !true | false |
&& | 短路与 | false&&true | false |
|| | 短路或 | false||true | true |
10.字符串的拼接有哪些方式?
使用加号(+)操作符:
javaCopy codeString str1 = "Hello";
String str2 = "world";
String result = str1 + " " + str2;
使用String的concat()方法:
javaCopy codeString str1 = "Hello";
String str2 = "world";
String result = str1.concat(" ").concat(str2);
使用StringBuilder类:
javaCopy codeStringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" ");
sb.append("world");
String result = sb.toString();
使用StringBuffer类(线程安全的版本,一般不推荐除非需要线程安全):
javaCopy codeStringBuffer sb = new StringBuffer();
sb.append("Hello");
sb.append(" ");
sb.append("world");
String result = sb.toString();
这些方法各有优缺点,一般来说,如果需要在循环中进行大量的字符串拼接操作,推荐使用StringBuilder,因为它是非线程安全的,性能更高。如果在多线程环境中进行字符串拼接操作,可以使用StringBuffer来确保线程安全。而使用加号操作符和concat()方法比较简单,适用于少量的字符串拼接操作。
11.Java三种注释方式
- 单行注释://
- 多行注释:/* */
- 文档注释:/** */
12.switch
switch 后面括号内的“表达式”必须是整数类型。也就是说可以是 int 型变量、char 型变量,也可以直接是整数或字符常量,哪怕是负数都可以。但绝对不可以是实数,float 型变量、double 型变量、小数常量通通不行,全部都是语法错误。
13.循环中的跳转语句
break
- 无法单独使用,必须将break关键字置于switch语句或循环语句中运行
- 不需要判断任何条件,只要遇到break变直接跳出执行后续代码。会完全跳出选择或者循环结构
- 只能跳出最近的代码块,不能跨越多级代码块
continue
- 提前结束本次循环,继续进行下次循环
- 无法单独使用,必须将continue关键字置于循环语句中
- 不需要判断任何条件,只要遇到continue变直接跳出本轮循环进行下次循环
return
- 执行这行语句后,之后的代码还执行吗?
(不执行)
14.数组
实操:定义一个3*5的数组并自己遍历出来
public class asd {
public static void main(String[] args) {
int [][][]arr= {{{1,2,3},{3,4,5},{3,9,7}},{{1,3,5},{4,5,2},{3,4,1}}};
for(int i=0;i<2;i++) {
for(int j=0;j<3;j++) {
for(int k=0;k<3;k++) {
System.out.print(arr[i][j][k]+" ");
}
System.out.println();
}
System.out.println();
}
}
}
数组的概述:数组是指一组数据的集合,数组中的每个数据被称作元素。在数组中可以存放任意类型的元素,但同一个数组里存放的元素类型必须一致。
数组的定义
-
格式:
数据类型[] 数组名 = new 数据类型[元素个数或数组长度];
-
举例:
int[] x = new int[100];
-
重点说明:
1)数据类型: 数组中存储元素的数据类型
2) [] 表示数组的意思
3) 变量名 自定义标识符
4) new 创建容器关键字
5)数据类型: 数组中存储元素的数据类型
6)元素个数,就是数组中,可以存储多少个数据 (恒定, 定长)
为数组的元素赋值有哪些方式?
int[] arr = new int[4]; // 定义可以存储4个整数的数组
arr[0] = 1; // 为第1个元素赋值1
arr[1] = 2; // 为第2个元素赋值2
类型[] 数组名 = new 类型[]{元素,元素,……};
int[] arr = new int[]{1,2,3,4};
类型[] 数组名 = {元素,元素,元素,……};
int[] arr = { 1, 2, 3, 4 };
foreach的使用
for(类型 变量名:集合){
语句块
}
15.如何理解类与对象的关系,请举例说明
- 类和对象的关系:
- 类是对某一类事物的抽象描述,而对象用于表示现实中该类事物的个体
- 举例:
- 可以将玩具模型看作是一个类,将一个个玩具看作对象,从玩具模型和玩具之间的关系便可以
16.方法
A.方法的格式:
修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2...) {
方法体语句;
return 返回值;
}
B.方法的格式说明:
-
修饰符:目前就用 public static。后面我们再详细的讲解其他的修饰符。
-
返回值类型:就是功能结果的数据类型。
-
实际参数:就是实际参与运算的。
-
形式参数;就是方法定义上的,用于接收实际参数的。
-
参数类型:就是参数的数据类型
-
参数名:就是变量名
-
方法体语句:就是完成功能的代码。
-
return:结束方法的。
-
返回值:就是功能的结果,由return带给调用者。
-
方法名:符合命名规则即可。方便我们的调用。
-
实际参数:就是实际参与运算的。
C.方法的定义和使用的注意事项:
- 方法不能定义在另一个方法的里面
- 写错方法名字
- 写错了参数列表
- 方法返回值是void,方法中可以省略return 不写,return 下面不能有代码
- 方法返回值类型,和return 后面数据类型必须匹配
- 方法重复定义问题
- 调用方法的时候,返回值是void, 不能写在输出语句中
17.自定义类
public class 类名{
//属性定义
修饰符 数据类型 变量名 = 值
//方法定义
修饰符 返回值类型 方法名(参数列表){
}
18.成员变量与局部变量的区别
- 区别一:定义的位置不同
- 定义在类中的变量是成员变量
- 定义在方法中或者{}语句里面的变量是局部变量
- 区别二:在内存中的位置不同
- 成员变量存储在堆内存的对象中
- 局部变量存储在栈内存的方法中
- 区别三:声明周期不同
- 成员变量随着对象的出现而出现在堆中,随着对象的消失而从堆中消失
- 局部变量随着方法的运行而出现在栈中,随着方法的弹栈而消失
- 区别四:初始化不同
- 成员变量因为在堆内存中,所以有默认的初始化值
- 局部变量没有默认的初始化值,必须手动的给其赋值才可以使用。
19.重载
在同一个类中,方法名相同,参数列表不同。与返回值类型无关。
参数列表不同:
- 参数个数不同
- 参数类型不同
- 参数的顺序不同(算重载,但是在开发中不用)
注意事项:
a: 参数列表必须不同
b: 重载和参数变量名无关
c: 重载和返回值类型无关
d: 重载和修饰符无关
e: 技巧: 重载看方法名和参数列表
方法参数:
- a: 方法参数是基本类型时,传递的是值。
- b: 方法参数是引用类型时,传递的是内存地址值。
20.构造方法
A.理解:
从字面上理解即为构建创造时用的方法,即就是对象创建时要执行的方法。既然是
对象创建时要执行的方法,那么只要在new对象时,知道其执行的构造方法是什么,
就可以在执行这个方法的时候给对象进行属性赋值。
B.构造方法的作用:
在new的同时给成员变量赋值,给对象属性进行初始化;
Person p = new Person(“张三”,23); 在new 的时候给p对象的name属性和age属
性进行赋值,使这个对象的属性有值。
C.构造方法的定义和运行条件:
构造方法的格式:
修饰符 构造方法名(参数列表) {
}
构造方法的体现:
- 构造方法没有返回值类型。也不需要写返回值。因为它是为构建对象的,对象创建完,方法就执行结束.
- 构造方法名称必须和类型保持一致。
- 构造方法没有具体的返回值。
构造方法的代码体现:
举例:
class Person {
// Person的成员属性age和name
private int age;
private String name;
// Person的构造方法,拥有参数列表
Person(int a, String nm) {
// 接受到创建对象时传递进来的值,将值赋给成员属性
age = a;
name = nm;
}
}
构造方法的运行特点:
在new 对象的时候自动调用执行;
D.当在描述事物时,要不要在类中写构造方法呢?
这时要根据描述事物的特点来确定,当描述的事物在创建其对象时就要明确属性的值,这时就需要在定义类的时候书写带参数的构造方法。若创建对象时不需要明确具体的数据,这时可以不用书写构造方法(不书写也有默认的构造方法)。
构造方法的细节:
1)一个类中可以有多个构造方法,多个构造方法是以重载的形式存在的
2)构造方法是可以被private修饰的,作用:其他程序无法创建该类的对象。
E.构造方法和一般方法的区别:
目前为止,学习两种方法,分别为构造方法和一般方法,那么他们之间有什么异同呢?
1.格式不同 构造方法 : 修饰符 类名(参数类型 参数 …){ 初始化成员变量 }
一般方法: 需要有返回值类型
2.作用不同 构造方法一般用来给成员变量初始化; 一般方法根据需求而定;
3.调用方式不同 构造方法创建对象时调用, 或者this() super() 语句调用 普通方法需要对象调用或者静态方法直接调用静态方法.
4.执行不同 构造方法在对象创建时就执行了,而且只执行一次。 一般方法是在对象创建后,需要使用时才被对象调用,并可以被多次调用。
F.this在构造方法之间调用
构造方法之间的调用,可以通过this关键字来完成。
构造方法调用格式:
this(参数列表);
21.static
概念
当在定义类的时候,类中都会有相应的属性和方法。而属性和方法都是通过创建本类对象调用的。当在调用对象的某个方法时,这个方法没有访问到对象的特有数据时,方法创建这个对象有些多余。可是不创建对象,方法又调用不了,这时就会想,那么我们能不能不创建对象,就可以调用方法呢可以的,我们可以通过static关键字来实现。static它是静态修饰符,一般用来修饰类中的成员。
static修饰的对象特有数据
被static修饰的成员变量属于类,不属于这个类的某个对象。(也就是说,多个对象在访问或修改static修饰的成员变量时,其中一个对象将static成员变量值进行了修改,其他对象中的static成员变量值跟着改变,即多个对象共享同一个static成员变量)
class Demo {
public static int num = 100;
}
class Test {
public static void main(String[] args) {
Demo d1 = new Demo();
Demo d2 = new Demo();
d1.num = 200;
System.out.println(d1.num); //结果为200
System.out.println(d2.num); //结果为200
}
}
static注意事项:静态不能直接调用非静态
- 被static修饰的成员可以并且建议通过类名直接访问。
- 访问静态成员的格式:
- 类名.静态成员变量名
- 类名.静态成员方法名(参数)
- 对象名.静态成员变量名 ------不建议使用该方式,会出现警告
- 对象名.静态成员方法名(参数) ------不建议使用该方式,会出现警告
c.举例:
class Demo {
//静态成员变量
public static int num = 100;
//静态方法
public static void method(){
System.out.println("静态方法");
}
}
class Test {
public static void main(String[] args) {
System.out.println(Demo.num);
Demo.method();
}
}
static的使用场景
使用场景:static可以修饰成员变量和成员方法。
1.什么时候使用static修饰成员变量?
加static修饰成员的时候,这个成员会被类的所有对象所共享。一般我们把共性数据定义为静态的变量
2.什么时候使用static修饰成员方法?
静态的方法只能访问静态的成员,如果静态方法中引用到了静态的其他成员,那么这个方法需要声明为静态的方法。
定义静态常量:
开发中,我们想在类中定义一个静态常量,通常使用public static final修饰的变量来完成定义。此时变量名用全部大写,多个单词使用下划线连接。
定义格式:
public static final 数据类型 变量名 = 值;
注意:接口中的每一个变量都默认使用public static final修饰;所有接口中的成员变量已是静态常量,由于接口没有构造方法,所以必须显示赋值。可以直接用接口名访问。
interface Inter {
public static final int COUNT = 100;
}
Inter.COUNT;
22.继承
A:继承的概念:
继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系
在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类被称作子类,现有类被称作父类
B:继承关系的子类特点 :
子类会自动拥有父类所有非private修饰的属性和方法
C:继承的格式:
class 子类 extends 父类 {};
D:继承的好处:
- 继承的出现提高了代码的复用性,提高软件开发效率。
- 继承的出现让类与类之间产生了关系,提供了多态的前提。
E:继承的注意事项:
- 在Java中,类只支持单继承,不允许多继承,也就是说一个类只能有一个直接父类。
- 多个类可以继承一个父类;
- 在Java中,多层继承是可以的, 即一个类的父类可以再去继承另外的父类;
- 在Java中,子类和父类是一种相对概念,也就是说一个类是某个类父类的同时,也可以是另一个类的子类。
F:继承后子类父类成员变量的特点 :
子类的对象调用成员变量的时候,子类自己有,使用子类,子类自己没有调用的父类。
在子类中需要访问父类中非私有成员变量时,需要使用super关键字.
G:继承后子类父类成员方法的特性_子类重写父类方法:
子类的对象调用方法的时候,子类自己有,使用子类,子类自己没有调用的父类
23.super关键字
A: 子父类中构造方法的调用
在创建子类对象时,父类的构造方法会先执行,因为子类中所有构造方法的第一行有默认的隐式super();语句。
B: 格式:
调用本类中的构造方法
this(实参列表);
调用父类中的空参数构造方法
super();
调用父类中的有参数构造方法
super(实参列表);
C.通过结果发现,子类构造方法执行时中,调用了父类构造方法,这说明,子类构造方法中有super()
那么,子类中的构造方法为什么会有一句隐式的super()呢?
原因:子类会继承父类中的内容,所以子类在初始化时,必须先到父类中去执行父类的 Q··
初始化动作。这样,才可以使用父类中的内容。
当父类中没有空参数构造方法时,子类的构造方法必须有显示的super语句,指定要访
问的父类有参数构造方法。
D.构造方法第一行,写this()还是super()?
this() 是调用本类的构造方法,super()是调用父类的构造方法, 且两条语句不能同时存在(他两都要放在方法里的第一行)
E.创建子类对象过程的细节:
A创建子类对象过程的细节
- 如果子类的构造方法第一行写了this调用了本类其他构造方法,那么super调用父类的语句还有吗?
- 这时是没有的,因为this()或者super(),只能定义在构造方法的第一行,因为初始化动作要先执行。
- 父类构造方法中是否有隐式的super呢?
- 也是有的。记住:只要是构造方法默认第一行都是super();
- 父类的父类是谁呢?super调用的到底是谁的构造方法呢?
- Java体系在设计,定义了一个所有对象的父类Object
注意:
- 类中的构造方法默认第一行都有隐式的super()语句,在访问父类中的空参数构造方法。所以父类的构造方法既可以给自己的对象初始化,也可以给自己的子类对象初始化。
- 如果默认的隐式super()语句在父类中没有对应的构造方法,那么必须在构造方法中通过this或者super的形式明确要调用的构造方法。
24.this的简单运用
当在方法中出现了局部变量和成员变量同名的时候,那么在方法中怎么区别局部变
量成员变量呢?可以在成员变量名前面加上this.来区别成员变量和局部变量。
举例:
class Person {
private int age;
private String name;
// 给姓名和年龄初始化的构造方法
Person(String name, int age) {
// 当需要访问成员变量是,只需要在成员变量前面加上this.即可
this.name = name;
this.age = age;
}
public void speak() {
5 System.out.println("name=" + this.name + ",age=" + this.age);
}
}
class PersonDemo {
public static void main(String[] args) {
Person p = new Person("张三", 23);
p.speak();
}
}
25.重写
要求:
- 子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表
- 子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型
- 子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限
- 子类不能重写父类中声明为private权限的方法
- 子类方法抛出的异常不能大于父类被重写方法的异常
注意:
子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为static的(不是重写)。因为static方法是属于类的,子类无法覆盖父类的方法。
26.多态
多态是同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作,(同一个事件发生在不同的对象上会产生不同的结果。)
优点:
- 消除类型之间的耦合关系
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性
向上向下转型
27.封装的概述:(重要)
面向对象三大特征
封装、继承、多态
封装表现
-
方法就是一个最基本封装体
-
类其实也是一个封装体
封装的好处(优点)
- 提高了代码的复用性
- 隐藏了实现细节,还要对外提供可以访问的方式。便于调用者的使用。这 是核心之一,也可以理解为就是封装的概念
- 提高了安全性
生活中的小例子:
机箱:
一台电脑,它是由CPU、主板、显卡、内存、硬盘、电源等部件组长,其实我们将这些部件组装在一起就可以使用电脑了,但是发现这些部件都散落在面, 很容造成不安全因素,于是,使用机箱壳子,把这些部件都装在里面,并在机箱壳上留下一些插口等,若不留插口,大家想想会是什么情况。
总结:机箱其实就是隐藏了办卡设备的细节,对外提供了插口以及开关等访问 内部细节的方式。
28.抽象类
分析事物时,发现了共性内容,就出现向上抽取。会有这样一种特殊情况,就是方法功能声明相同,但方法功能主体不同。那么这时也可以抽取,但只抽取方法声明,不抽取方法主体。那么此方法就是一个抽象方法。
抽象方法的定义格式:
public abstract 返回值类型 方法名(参数);
抽象类的定义格式:
abstract class 类名 {}
29.接口
A.类与接口的关系:
类与接口的关系为实现关系,即类实现接口。实现的动作类似继承,只是关键字不同,实现使用implements。
B.类实现接口的方式:
class 类 implements 接口 {
//重写接口中方法
}
C.注意事项:
1.在类实现接口后,该类就会将接口中的抽象方法继承过来,此时该类需要重写该抽象方法,完成具体的逻辑。
2.接口中定义功能,当需要具有该功能时,可以让类实现该接口,只声明了应该具备该方法,是功能的声明。
3.在具体实现类中重写方法,实现功能,是方法的具体实现。
D.接口中成员方法的特点:
接口中可以定义方法,方法也有固定的修饰符,public abstract * b 子类必须覆盖掉接口中所有的抽象方法后,子类才可以实例化。否则子类是一个抽象类。
案例:
class DemoImpl implements Demo { //子类实现Demo接口。
//重写接口中的方法。
public void show1(){}
public void show2(){}
}
interface Demo { ///定义一个名称为Demo的接口。
public abstract void show1();
public abstract void show2();
}
//定义子类去覆盖接口中的方法。类与接口之间的关系是 实现。通过关键字 implements
class DemoImpl implements Demo { //子类实现Demo接口。
//重写接口中的方法。
public void show1(){}
public void show2(){}
}
E.接口的实现类:
一个类如果实现类接口,有两种操作方法: 第一:实现类是非抽象类,就需要重写接口中所有的抽象方法. 第二:实现类也声明为抽象类,那么实现类可以不重写接口中的抽象方法。
F.接口的多实现了解了接口的特点后,那么想想为什么要定义接口
使用抽象类描述也没有问题,接口到底有啥用呢?接口最重要的体现:解决多继承的弊端。将多继承这种机制在java中通过多实现完成了。
接口的多继承
学习类的时候,知道类与类之间可以通过继承产生关系,接口和类之间可以通过实现产生关系,那么接口与接口之间会有什么关系。
多个接口之间可以使用extends进行继承。
H.接口和抽象类区别总结:
相同点:
- 都位于继承的顶端,用于被其他类实现或继承;
- 都不能直接实例化对象;
- 都包含抽象方法,其子类都必须覆写这些抽象方法;
区别:
- 抽象类为部分方法提供实现,避免子类重复实现这些方法,提高代码重用性;接口只能包含抽象方法;
- 一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥补了Java的单继承)
- 抽象类是这个事物中应该具备的你内容, 继承体系是一种 is…a关系
- 接口是这个事物中的额外内容,继承体系是一种 like…a关系
二者的选用:
- 优先选用接口,尽量少用抽象类;
- 需要定义子类的行为,又要为子类提供共性功能时才选用抽象类;
30.Final的使用
修饰类
当用final修饰一个类时,表明这个类不能被继承。也就是说,如果一个类你永远不会让他被继承,就可以用final进行修饰。final类中的成员变量可以根据需要设为final,但是要注意final类中的所有成员方法都会被隐式地指定为final方法。
修饰方法
下面这段话摘自《Java编程思想》第四版第143页:
使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。在最近的Java版本中,不需要使用final方法进行这些优化了。
因此,如果只有在想明确禁止该方法在子类中被覆盖的情况下才将方法设置为final的。
注:类的private方法会隐式地被指定为final方法。
修饰变量
对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
31.匿名对象
A.匿名对象的概述:
匿名对象是指创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量。
B.案例:
public class Person{
public void eat(){
System.out.println();
}
}
//创建一个普通对象
Person p = new Person();
//创建一个匿名对象
new Person();
C.匿名对象的特点:
1):创建匿名对象直接使用,没有变量名。
new Person().eat() //eat方法被一个没有名字的Person对象调用了
2):匿名对象在没有指定其引用变量时,只能使用一次。
new Person().eat(); 创建一个匿名对象,调用eat方法
new Person().eat(); 想再次调用eat方法,重新创建了一个匿名对象
3):匿名对象可以作为方法接收的参数、方法返回值使用:
class Demo {
public static Person getPerson(){
//普通方式
//Person p = new Person();
//return p;
//匿名对象作为方法返回值
return new Person();
}
public static void method(Person p){}
}
class Test {
public static void main(String[] args) {
//调用getPerson方法,得到一个Person对象
Person person = Demo.getPerson();
//调用method方法
Demo.method(person);
//匿名对象作为方法接收的参数
Demo.method(new Person());
}
}
32.内部类
A.内部类的概述:
将类写在其他类的内部,可以写在其他类的成员位置和局部位置,这时写在其他类内部的类就称为内部类。其他类也称为外部类。
B.什么时候使用内部类:
在描述事物时,若一个事物内部还包含其他可能包含的事物,比如在描述汽车时,汽车中还包含这发动机,这时发动机就可以使用内部类来描述。 class 汽车 { //外部类 class 发动机 { //内部类 } }
C.内部类的分类:
内部类分为成员内部类与局部内部类。我们定义内部类时,就是一个正常定义类的过程,同样包含各种修饰符、继承与实现关系等。在内部类中可以直接访问外部类的所有成员。
成员内部类,定义在外部类中的成员位置。与类中的成员变量相似,可通过外部类对象进行访问
定义格式:
class 外部类 {
修饰符 class 内部类 {
//其他代码
}
}
访问方式:
外部类名.内部类名 变量名 = new 外部类名().new 内部类名();
代码演示:
成员内部类
代码演示
class Body {//外部类,身体
private boolean life= true; //生命状态
public class Heart { //内部类,心脏
public void jump() {
System.out.println("心脏噗通噗通的跳")
System.out.println("生命状态" + life); //访问外部类成员变量
}
}
}
//访问内部类
public static void main(String[] args) {
//创建内部类对象
Body.Heart bh = new Body().new Heart();
//调用内部类中的方法
bh.jump();
}
局部内部类
局部内部类,定义在外部类方法中的局部位置。与访问方法中的局部变量相似,可通过调用方法进行访问.
定义格式:
class 外部类 {
修饰符 返回值类型 方法名(参数) {
class 内部类 {
//其他代码
}
}
}
访问方式:
在外部类方法中,创建内部类对象,进行访问
案例代码:
class Party {//外部类,聚会
public void puffBall(){// 吹气球方法
class Ball {// 内部类,气球
public void puff(){
System.out.println("气球膨胀了");
}
}
//创建内部类对象,调用puff方法
new Ball().puff();
}
}
//访问内部类
public static void main(String[] args) {
//创建外部类对象
Party p = new Party();
//调用外部类中的puffBall方法
p.puffBall();
}
现在外部类中调用内部类的方法访问内部类。然后可以调用外部类来调用外部类中内部类的内容;
匿名内部类
概述:
内部类是为了应对更为复杂的类间关系。查看源代码中会涉及到,而在日常业务中很难遇到,这里不做赘述。最常用到的内部类就是匿名内部类,它是局部内部类的一种。
本质:
匿名内部类的本质是一个实现了接口或继承了某个类的子类匿名对象.
33.枚举
一枚一枚可以例举出来的,才建议使用枚举类型;
枚举编译之后也是生成class文件,
枚举也是一种引用数据类型,
枚举中的每一个值都可以看做是一个常量。
例如:
enum Result{
SUCESS,FALL
}
SUCCESS,FALL都是枚举Result类型中的一个值。枚举中的每一个值都可以看作是“常量”
总结:
1.枚举是一种引用数据类型
2.枚举类型怎么定义,语法是?
enum 枚举类型名{
枚举值1,枚举值2...
}
3.结果只有两种情况的,建议使用布尔类型,结果超过两种的并且可以一个一个列举出来的,建议使用枚举类型。例如:颜色,四季,
4.switch也支持枚举类型,switch也支持String,int,高版本jgk还支持,byte,short,char,因为存在自动类型转换。
34.包(了解)
java的包,其实就是我们电脑系统中的文件夹,包里存放的是类文件。当类文件很多的时候,通常我们会采用多个包进行存放管理他们,这种方式称为分包管理。在项目中,我们将相同功能的类放到一个包中,方便管理。并且日常项目的分工也是以包作为边界。类中声明的包必须与实际class文件所在的文件夹情况相一致,即类声明在a包下,则生成的.class文件必须在a文件夹下,否则,程序运行时会找不到类。
35.权限修饰符
在Java中提供了四种访问权限,使用不同的访问权限时,被修饰的内容会有不同的访问权限,以下表来说明不同权限的访问能力:
public | protected | default | private | |
---|---|---|---|---|
同一类中 | √ | √ | √ | √ |
同一包中(子类与无关类) | √ | √ | √ | |
不同包的子类 | √ | √ | ||
不同包中的无关类 | √ |
不同修饰符的使用细节
A:常用来修饰类,方法,变量的修饰符细节;
- public 权限修饰符,公共访问, 类,方法,成员变量
- protected 权限修饰符,受保护访问, 方法,成员变量
- 默认什么也不写 也是一种权限修饰符,默认访问, 类,方法,成员变量
- private 权限修饰符,私有访问, 方法,成员变量
- static 静态修饰符 方法,成员变量
- final 最终修饰符 类,方法,成员变量,局部变量
- abstract 抽象修饰符 类 ,方法
B: 不能同时使用的修饰符
- abstract与private不能同时使用;
- bstract与static不能同时使用;
- abstract与final不能同时使用。
C: 修饰类能够使用的修饰符: 修饰类只能使用public、默认的、final、abstract关键字 使用最多的是 public关键字
代码案例
public class Demo {} //最常用的方式
class Demo2{}
public final class Demo3{}
public abstract class Demo4{}
D:修饰成员变量能够使用的修饰符:
public : 公共的
protected : 受保护的: 默认的
private :私有的
final : 最终的
static : 静态的
使用最多的是 private
a: 代码案例:
public int count = 100;
protected int count2 = 100;
int count3 = 100;
private int count4 = 100; //最常用的方式
public final int count5 = 100;
public static int count6 = 100;
E:修饰构造方法能够使用的修饰符: public : 公共的 protected : 受保护的: 默认的 private :私有的 使用最多的是 public
a:代码案例:
public Demo(){} //最常用的方式
protected Demo(){}
Demo(){}
private Demo(){}
F:修饰成员方法能够使用的修饰符:
public : 公共的
protected : 受保护的: 默认的
private :私有的
final : 最终的
static : 静态的
abstract : 抽象的
使用最多的是 public
public void method1(){}//最常用的方式:
protected void method2(){}
void method3(){}
private void method4(){}
public final void method5(){}
public static void method6(){}//最常用的方式
public abstract void method7();//最常用的方式
36.ArrayList的简单使用
ArrayList创建变量的步骤
a: 导入包 java.util包
b: 创建引用类型的变量
数据类型<集合存储的数据类型> 变量名 = new 数据类型<集合存储的数据类型>();
创建集合引用变量的时候,必须要指定好存储的类型是什么
c: 变量名.方法
ArrayList创建变量举例:
import java.util.ArrayList;
public class ArrayListDemo{
public static void main(String[] args){
//创建集合容器,指定存储的数据类型
//存储字符串
ArrayList<String> array = new ArrayList()<String>;
//创建集合容器,存储整数
ArrayList<Integer> array2 = new ArrayList()<Integer>;
//创建集合容器,存储手机类型
ArrayList<Phone> array3 = new ArrayList()<Phone>;
}
}
ArrayList的常见方法:
ArrayList的常见方法:
a: add(参数) 向集合中添加元素
b: get(int index) 取出集合中的元素,get方法的参数,写入索引
c: size() 返回集合的长度, 集合存储元素的个数
案例代码:
import java.util.ArrayList;
public class Test_006 {
public static void main(String[] args) {
ArrayList<String> array = new ArrayList()<String>;
//调用集合方法 add()储存元素
//此处使用的是String 所以add里面的添加元素主要家引号;
array.add("abc");
array.add("123");
array.add("java");
//输出集合的长度,调用集合的方法size,size方法的返回值类型int;
int size = array.size();
System.out.println(size);
//利用get()方法获得1索引的元素;
String s = array.get(1);
System.out.println(s);
}
}
ArrayList集合的遍历:
实现思想也是索引思想
集合的索引从0开始,到 size()-1
方法get(int index)
实操代码:
package luke;
import java.util.ArrayList;
public class Test_007 {
public static void main(String[] args) {
ArrayListarray=new ArrayList()<Integer>;
array.add(123);
array.add(654);
array.add(987);
array.add(852);
array.add(963);
for(int i=0;i<array.size();i++) {
System.out.println(array.get(i));
}
}
}
ArrayList补充方法:
-
add(int 索引,存储的元素)
将元素添加到指定的索引上
-
set(int 索引,修改后的元素)
将指定索引的元素,进行修改
-
remove(int 索引)
删除指定索引上的元素
-
clear()
清空集合中的所有元素
37.接口与适配器的区别:
适配器:只是一个类,此类中实现了接口中的定义方法,并对方法进行重写,以达到特定的目的。
接口(interface):实际上就是定义了某些规范的java方法,只提供方法的定义,而不具体的进行实现,也就是类中都是抽象方法;
- 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法。
- 接口不能包含成员变量,除了 static 和 final 变量。
- 接口不是被类继承了,而是要被类实现。
- 接口支持多继承。
区别:适配器只需重写需要的事件处理方法,而接口需要实现全部的方法。
38.Java随机数
通过System.currentTimeMillis()来获取随机数。
实际上是获取当前时间毫秒数,它是long类型。使用方法如下:
final long l = System.currentTimeMillis();
若要获取int类型的整数,只需要将上面的结果转行成int类型即可。比如,获取[0, 100)之间的int整数。方法如下:
final long l = System.currentTimeMillis();
final int i = (int)( l % 100 );
通过Math.random()来获取随机数。
实际上,它返回的是0(包含)到1(不包含)之间的double值。使用方法如下:
final double d = Math.random();
若要获取int类型的整数,只需要将上面的结果转行成int类型即可。比如,获取[0, 100)之间的int整数。方法如下:
final double d = Math.random();
final int i = (int)(d*100);
39.==和equal的联系与区别:
最大的区别是,== 是运算符,equal是方法
简述几种情况下的equal和 ==
- 比较基本类型
- 只能用 == ,不能用equal,这里的 == 比较的是两个变量的
- 比较包装类型
- 比较的是内存地址,因为a和b是new出来的,是两个不同的对象,所以地址肯定是不同的,而equal比较的是值,
- 比较String类型
- ==比较的是内存地址,equals比较的是值
- 比较对象
- ==和equal比较的都是内存地址,因为equal没有被重写,没有被重写的equal都是object的equal方法
加粗样式
- ==和equal比较的都是内存地址,因为equal没有被重写,没有被重写的equal都是object的equal方法
40.线程的五种状态
线程共包括以下 5 种状态:
1. 新建状态(New): 线程对象被创建后,就进入了新建状态。例如,Thread thread = new Thread()。
2. 就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。
3. 运行状态(Running): 线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。
4. 阻塞状态(Blocked): 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
- 等待阻塞 – 通过调用线程的wait()方法,让线程等待某工作的完成。
- 同步阻塞 – 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
- 其他阻塞 – 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5. 死亡状态(Dead): 线程执行完了或者因异常退出了run()方法,该线程结束生命周期。