目录
java基础知识
-
Java语言跨平台原理(理解)
Java程序并非是直接运行的,Java编译器将Java源程序编译成与平台无关的字节码文件(class文件),然后由Java虚 拟机(JVM)对字节码文件解释执行。所以在不同的操作系统下,只需安装不同的Java虚拟机即可实现java程序的 跨平台。
-
JRE(Java Runtime Environment)
是java程序的运行时环境,包含 jvm 和运行时所需的核心类库。
-
JDK(Java Development Kit)
是java程序开发工具包,包含JRE和开发人员使用的开发工具
开发工具:编译工具(javac.exe),运行工具(java.exe)。
-
关键字:
特点关键字字母全部都是小写
关键字 | 含义 |
abstract | 表明类或者成员方法具有抽象属性 |
assert | 断言,用来进行程序调试 |
boolean | 基本数据类型之一,声明布尔类型的关键字 |
break | 提前跳出一个块 |
byte | 基本数据类型之一,字节类型 |
case | 用在switch语句之中,表示其中的一个分支 |
catch | 用在异常处理中,用来捕捉异常 |
char | 基本数据类型之一,字符类型 |
class | 声明一个类 |
const | 保留关键字,没有具体含义 |
continue | 回到一个块的开始处 |
default | 默认,例如,用在switch语句中,表明一个默认的分支。Java8 中也作用于声明接口函数的默认实现 |
do | 用在do-while循环结构中 |
double | 基本数据类型之一,双精度浮点数类型 |
else | 用在条件语句中,表明当条件不成立时的分支 |
enum | 枚举 |
extends | 表明一个类型是另一个类型的子类型。对于类,可以是另一个类或者抽象类;对于接口,可以是另一个接口 |
final | 用来说明最终属性,表明一个类不能派生出子类,或者成员方法不能被覆盖,或者成员域的值不能被改变,用来定义常量 |
finally | 用于处理异常情况,用来声明一个基本肯定会被执行到的语句块 |
float | 基本数据类型之一,单精度浮点数类型 |
for | 一种循环结构的引导词 |
goto | 保留关键字,没有具体含义 |
if | 条件语句的引导词 |
implements | 表明一个类实现了给定的接口 |
import | 表明要访问指定的类或包 |
instanceof | 用来测试一个对象是否是指定类型的实例对象 |
int | 基本数据类型之一,整数类型 |
interface | 接口 |
long | 基本数据类型之一,长整数类型 |
native | 用来声明一个方法是由与计算机相关的语言(如C/C++/FORTRAN语言)实现的 |
new | 用来创建新实例对象 |
package | 包 |
private | 一种访问控制方式:私用模式 |
protected | 一种访问控制方式:保护模式 |
public | 一种访问控制方式:共用模式 |
return | 从成员方法中返回数据 |
short | 基本数据类型之一,短整数类型 |
static | 表明具有静态属性 |
strictfp | 用来声明FP_strict(单精度或双精度浮点数)表达式遵循IEEE 754算术规范 |
super | 表明当前对象的父类型的引用或者父类型的构造方法 |
switch | 分支语句结构的引导词 |
synchronized | 表明一段代码需要同步执行 |
this | 指向当前实例对象的引用 |
throw | 抛出一个异常 |
throws | 声明在当前定义的成员方法中所有需要抛出的异常 |
transient | 声明不用序列化的成员域 |
try | 尝试一个可能抛出异常的程序块 |
void | 声明当前成员方法没有返回值 |
volatile | 表明两个或者多个变量必须同步地发生变化 |
while | 用在循环结构中 |
-
计算机的存储单元:
计算机存储设备的最小信息单元叫: 位(bit)/比特位(b)
计算机最小的存储单元叫:字节 (byte)通常用大写字母B表示,字节是连续的8个位组成
换算公式:
1B(字节)=8bit(b)
1KB=1024B
1MB=1024KB
1G=1024MB
1T=1024G
-
数据类型
数据类型 | 关键字 | 内存占用 | 取值范围 |
整数类型
| byte | 1 | -128~127 |
short | 2 | -32768~32767 | |
int(默认) | 4 | -2的31次方到2的31次方-1 | |
long | 8 | -2的63次方到2的63次方-1 | |
浮点类型
| float | 4 | 负数:-3.402823E+38到-1.401298E-45 正数: 1.401298E-45到 3.402823E+38 |
double(默认) | 8 | 负数:-1.797693E+308到-4.9000000E-324 正数:4.9000000E-324 到 1.797693E+308 | |
字符类型 | char | 2 | 0-65535 |
布尔类型 | boolean | 1 | true,false |
说明:e+38表示是乘以10的38次方,同样,e-45表示乘以10的负45次方。在java中整数默认是int类型,浮点数默认是double类型。
-
标识符:就是给类,方法,变量等起名字的符号
Java中标识符的组成规则:
-
由字母、数字、下划线“_”、美元符号“$”组成
-
不能以数字开头。
-
不能是关键字。
-
区分大小写。
Java中标识符的命名约定:
-
小驼峰式命名:变量名、方法名
首字母小写,从第二个单词开始每个单词的首字母大写。
-
大驼峰式命名:类名
每个单词的首字母都大写。
另外,标识符的命名最好可以做到见名知意
-
数据类型转换
自动类型转换
//String转数字类型
String s = "169";
byte b = Byte.parseByte( s );
short t = Short.parseShort( s );
int i = Integer.parseInt( s );
long l = Long.parseLong( s );
Float f = Float.parseFloat( s );
Double d = Double.parseDouble( s );
//数字类型转String
String a = Integer.toString(num);
-
算术运算符
符号 | 作用 | 说明 |
+ | 加 | 参看小学一年级 |
- | 减 | 参看小学一年级 |
* | 乘 | 参看小学二年级,与“×”相同 |
/ | 除 | 参看小学二年级,与“÷”相同 |
% | 取余 | 获取的是两个数据做除法的余数 |
小数取整:
Math.ceil()执行向上舍入,即它总是将数值向上舍入为最接近的整数,返回值为Double类型;
Math.floor()执行向下舍入,即它总是将数值向下舍入为最接近的整数,返回值为Double类型;
Math.round()执行标准舍入,即它总是将数值四舍五入为最接近的整数,返回值为Long类型;
-
赋值运算符
符号 | 作用 | 说明 |
= | 赋值 | a=10,将10赋值给变量a |
+= | 加后赋值 | a+=b,将a+b的值给a |
-= | 减后赋值 | a-=b,将a-b的值给a |
*= | 乘后赋值 | a*=b,将a×b的值给a |
/= | 除后赋值 | a/=b,将a÷b的商给a |
%= | 取余后赋值 | a%=b,将a÷b的余数给a |
注意:扩展的赋值运算符隐含了强制类型转(+=,-=,*=,/=,%=)
short num = 10;
num += 20; //正常: += 封装了强制类型转换,等价于num = (short)(num + 20);
num = num + 20; // 报错: num + 20 返回值为int,但是num是short类型
符号 | 作用 | 说明 |
<< | 左移运算符 | 例如8<<2,表示将8向左移2位,结果为32。低位补0。二进制演算:8的二进制:1 0 0 0向左移动两位结果为1 0 0 0 0 0,换算成十进制即为32,也可以简单的理解为,左移就是将数变大,相当于8*2^2=32。 |
>> | 右移运算符 | 例如 8>>2,表示将8向右移动2位,结果为2。高位补0。 |
-
自增自减运算符
符号 | 作用 | 说明 |
++ | 自增 | 变量的值加1 |
-- | 自减 | 变量的值减1 |
注意事项:
++和-- 既可以放在变量的后边,也可以放在变量的前边。
单独使用的时候, ++和-- 无论是放在变量的前边还是后边,结果是一样的。
参与操作的时候,如果放在变量的后边,先拿变量参与操作,后拿变量做++或者--。参与操作的时候,如果放在变量的前边,先拿变量做++或者--,后拿变量参与操作。最常见的用法:单独使用。
自加自减的操作在当前表达式就已经完成
int i = 10;
int j = i++;
int y = 10;
int x = ++y;
System.out.println(i); //11
System.out.println(j); //10
System.out.println(y); //11
System.out.println(x); //11
-
逻辑运算符
符号 | 作用 | 说明 |
& | 逻辑与 | a&b,a和b都是true,结果为true,否则为false |
| | 逻辑或 | a|b,a和b都是false,结果为false,否则为true |
^ | 逻辑异或 | a^b,a和b结果不同为true,相同为false |
! | 逻辑非 | !a,结果和a的结果正好相反 |
逻辑异或:相同为false,不同为true
System.out.println((1>2) ^ (1<2));//false ^ true //true
System.out.println((1<2) ^ (1>2));//true ^ false //true
System.out.println((1<2) ^ (1<2));//true ^ true //false
System.out.println((1>2) ^ (1>2));//false ^ false //false
-
短路逻辑运算符
符号 | 作用 | 说明 |
&& | 短路与 | 作用和&相同,但是有短路效果 |
|| | 短路或 | 作用和|相同,但是有短路效果 |
在逻辑与运算中,只要有一个表达式的值为false,那么结果就可以判定为false了,没有必要将所有表达式的值都计算出来,短路与操作就有这样的效果,可以提高效率。同理在逻辑或运算中,一旦发现值为true,右边的表达式将不再参与运算。
-
三元运算符
关系表达式 ? 表达式1:表达式2
解释:问号前面的位置是判断的条件,判断结果为boolean型,为true时调用表达式1,为false时调用表达式2。其逻辑为:如果条件表达式成立或者满足则执行表达式1,否则执行第二个。
int a = 10;
int b = 20;
int result3 = a > b ? a:b;
System.out.println("max: " + result3);
int result4 = a < b ? a:b;
System.out.println("min: " + result4);
//-------------------------------------result----------------------------
max: 20
min: 10
-
流程控制语句
-
顺序结构
顺序结构: 是程序中最简单最基本的流程控制,没有特定的语法结构,按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。
-
分支结构(if, switch)
①首先计算关系表达式的值
②如果关系表达式的值为true就执行语句体
③如果关系表达式的值为false就不执行语句体
④继续执行后面的语句内容
-
循环结构(for, while, do…while)
-
switch case穿透
注意事项: 在switch case语句中,如果case控制的语句后面不写break,将会出现穿透现象,在不判断下一个case值的情况下继续向下运行,直到遇到break或者switch case语句结束。
int value = 5;
switch(value){
case 1:
case 4:
case 7:
System.out.println("1是地主");
break;
case 2:
case 5:
case 8:
System.out.println("2是地主");
break;
case 3:
case 6:
case 9:
System.out.println("3是地主");
break;
default:
System.out.println("都不是地址");
//-------------------------result-----------------------
2是地主
int value = 5;
switch(value) {
case 1:
System.out.println("111111");
case 4:
case 7:
System.out.println("1是地主");
break;
case 2:
case 5:
System.out.println("55555555");
case 12:
System.out.println("12121212");
case 8:
System.out.println("2是地主");
break;
case 3:
case 6:
case 9:
System.out.println("3是地主");
break;
default:
System.out.println("都不是地址");
}
//-------------------------result-----------------------
55555555
12121212
2是地主
-
三种循环的区别
三种循环的区别
for循环和while循环先判断条件是否成立,然后决定是否执行循环体(先判断后执行)
do...while循环先执行一次循环体,然后判断条件是否成立,是否继续执行循环体(先执行后判断)
for循环和while的区别
条件控制语句所控制的自增变量,因为归属for循环的语法结构中,在for循环结束后,就不能再次被访问到了
条件控制语句所控制的自增变量,对于while循环来说不归属其语法结构中,在while循环结束后,该变量还可以继续使用
死循环(无限循环)的三种格式
-
for(;;){}
-
while(true){} (最常用)
-
do {} while(true);
int n = 5;
while (++n <= 10) {
System.out.println(n);
}
System.out.println("-------------------");
int i = 5;
while (i++ <= 10) {
System.out.println(i);
}
//-------------------------result---------------------------------
6
7
8
9
10
-------------------
6
7
8
9
10
11
-
获取随机数 Random
Random random = new Random();
int ra = random.nextInt(10);
//10代表的是一个范围,如果括号写10,产生的随机数就是0-9,包含下限,不包含上限
System.out.println(ra);
-
IDEA常用快捷键
快捷键 | 功能 |
Alt+Enter | 导入包,自动修正代码 |
Ctrl+Y | 删除光标所在行 |
Ctrl+D | 复制光标所在行的内容,插入光标位置下面 |
Ctrl+Alt+L | 格式化代码 |
Ctrl+/ | 单行注释 |
Ctrl+Shift+/ | 选中代码注释,多行注释,再按取消注释 |
Alt+Shift+上下箭头 | 移动当前代码行 |
Ctrl+B | 查看方法源码 |
ALT+7 | 查看类的成员变量、方法目录 |
Ctrl+Alt+V | 自动补齐等号左边的声明代码 |
Ctrl+Shift+V | 查看粘贴板历史内容 |
ctrl + alt +B | 查找接口的实现类 |
ALT +INSERT | 快速实现接口快捷方式 |
内容辅助键
Ctrl + Alt +space: 内容提示,代码补全等
快速生成语句
快速生成main()方法: psvm + 回车
快速生成输出语句: sout + 回车
-
数组
常用输出格式:
int[] arr = new int[10];
System.out.println(Arrays.toString(arr));
String[] arrstr = new String[10];
System.out.println(Arrays.toString(arrstr));
//--------------result-------------------
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[null, null, null, null, null, null, null, null, null, null]
数组定义格式
第一种: 数据类型[] 数组名 int[] arr = new int[]; (常用第一种)
定义了一个int类型的数组,数组名是arr
第二种: 数据类型 数组名[] int arr[] = new int[];
定义了一个int类型的变量,变量名是arr数组
数组静态初始化
在创建数组时,指定每个元素的初始值,有系统决定数组长度
格式: 数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, 元素3...}
简化格式:数据类型[] 数组名 = {元素1, 元素2, 元素3...}
数组动态初始化
数组动态初始化就是只给定数组的长度,由系统给出默认初始化值
整数默认为:0
浮点数默认为:0.0
布尔值默认为: false
字符默认为: 空格(空字符)
引用数据类型默认为:null (Double,Float等是null)
char[] ch = new char[1];
System.out.println(ch[0]); //空格
if(ch[0] =='\0'){
System.out.println("ch[0] is space"); //ch[0] is space
}
String[] arr2 = new String[1];
System.out.println(arr2[0]); //null
int[] arr1 = new int[1];
System.out.println(arr1[0]); //0
double[] dou = new double[1];
System.out.println(dou[0]); //0.0
Double[] dob = new Double[1];
System.out.println(dob[0]); //null
float[] flo = new float[1];
System.out.println(flo[0]); //0.0
Float[] flot = new Float[1];
System.out.println(flot[0]); //null
-
内存分配
int[] arr = new int[3];
- 栈内存:存储局部变量(定义在方法中的变量),例如arr,使用完毕立即消失
- 堆内存:存储new出来的内容(实体,对象)
数组在初始化时,会为存储空间添加默认值:
整数默认为:0
浮点数默认为:0.0
布尔值默认为: false
字符默认为: 空格(空字符)
引用数据类型默认为:null (Double,Float等是null)
每一个new出来的东西都有一个地址值,使用完毕,会在垃圾回收器空闲时被回收
区域名称 | 作用 |
寄存器 | 给CPU使用,和我们开发无关。 |
本地方法栈 | JVM在使用操作系统功能的时候使用,和我们开发无关。 |
方法区 | 存储可以运行的class文件。 |
堆内存 | 存储对象或者数组,new来创建的,都存储在堆内存。 |
方法栈 | 方法运行时使用的内存,比如main方法运行,进入方法栈中执行。 |
-
for多个条件控制
int[] arr = new int[]{1,2,3,45,6,7,8,9,10};
for(int i=0,j=arr.length-1; i<=j; i++,j--){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
-
类和对象的理解
类的理解
类是对现实生活中一类具有共同属性和行为的事物的抽象
类是对象的数据类型,类是具有相同属性和行为的一组对象的集合简单理解:类就是对现实事物的一种描述类的组成
属性:指事物的特征,例如:手机事物(品牌,价格,尺寸)
行为:指事物能执行的操作,例如:手机事物(打电话,发短信)类和对象的关系
类:类是对现实生活中一类具有共同属性和行为的事物的抽象对象:是能够看得到摸的着的真实存在的实体
简单理解:类是对事物的一种描述,对象则为具体存在的事物
类的组成是由属性和行为两部分组成
属性:在类中通过成员变量来体现(类中方法外的变量)
行为:在类中通过成员方法来体现(和前面的方法相比去掉static关键字即可)类的定义
-
成员变量和局部变量
成员变量和局部变量的区别
类中位置不同:成员变量(类中方法外)局部变量(方法内部或方法声明上)内存中位置不同:成员变量(堆内存)局部变量(栈内存)
生命周期不同:成员变量(随着对象的存在而存在,随着对象的消失而消失)局部变量(随着方法的调用而存在,醉着方法的调用完毕而消失)
初始化值不同:成员变量(有默认初始化值)局部变量(没有默认初始化值,必须先定义,赋值才能使用)
-
创建字符串对象两种方式的区别
通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同 直接赋值方式创建
以“”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一个 String 对象,并在字符串池中维护
-
字符串的比较
==号的作用
比较基本数据类型:比较的是具体的值
比较引用数据类型:比较的是对象地址值
equals方法的作用
比较的是具体的值
-
StringBuilder类和String类的区别
String类:内容是不可变的
StringBuilder类:内容是可变的
-
StringBuilder和String相互转换
StringBuilder转换为String
public String toString():通过 toString() 就可以实现把 StringBuilder 转换为 String
String转换为StringBuilder
public StringBuilder(String s):通过构造方法就可以实现把 String 转换为 StringBuilder
-
ArrayList类概述
什么是集合
提供一种存储空间可变的存储模型,存储的数据容量可以发生改变
ArrayList集合的特点
底层是数组实现的,长度可以变化 泛型的使用
用于约束集合中存储元素的数据类型
构造方法
方法名 | 说明 |
public ArrayList() | 创建一个空的集合对象 |
成员方法
方法名 | 说明 |
public boolean remove(Object o) | 删除指定的元素,返回删除是否成功 |
public E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
public E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
public E get(int index) | 返回指定索引处的元素 |
public int size() | 返回集合中的元素的个数 |
public boolean add(E e) | 将指定的元素追加到此集合的末尾 |
public void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
ArrayList<Integer> test = new ArrayList<Integer>();
test.add(9).add(8).add(7).add(6);
System.out.println(test);
//System.out.println(test.remove(9)); 错误的做法,此处的9会认为是索引而非元素
System.out.println(test.remove((Integer)9));
System.out.println(test);
-
封装
-
封装概述 是面向对象三大特征之一(封装,继承,多态) 是面向对象编程语言对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界是无法直接操作的
-
封装原则 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问 成员变量private,提供对应的getXxx()/setXxx()方法
-
封装好处 通过方法来控制成员变量的操作,提高了代码的安全性 把代码用方法进行封装,提高了代码的复用性
-
继承
继承的概念
继承是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及追加属性和方法实现继承的格式
继承通过extends实现
格式:class 子类 extends 父类 { }
举例:class Dog extends Animal { }
-
继承的好处和弊端
继承好处
- 提高了代码的复用性(多个类相同的成员可以放到同一个类中)
- 提高了代码的维护性(如果方法的代码需要修改,修改一处即可)
继承弊端
继承让类与类之间产生了关系,类的耦合性增强了,当父类发生变化时子类实现也不得不跟着变化,削弱了子类的独立性
继承的应用场景:
使用继承,需要考虑类与类之间是否存在is..a的关系,不能盲目使用继承
is..a的关系:谁是谁的一种,例如:老师和学生是人的一种,那人就是父类,学生和老师就是子类
-
super
this:代表本类对象的引用
super:代表父类存储空间的标识(可以理解为父类对象引用) this和super的使用分别
this和super的区别
-
继承中构造方法的访问特点
注意:子类中所有的构造方法默认都会访问父类中无参的构造方法
子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化,原因在于,每一个子类构造方法的第一条语句默认都是:super()
-
方法重写
- 方法重写概念
子类出现了和父类中一模一样的方法声明(方法名一样,参数列表也必须一样)
- 方法重写的应用场景
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容
- Override注解
用来检测当前的方法,是否是重写的方法,起到【校验】的作用
方法重写的注意事项
- 私有方法不能被重写(父类私有成员子类是不能继承的)
- 子类方法访问权限不能更低(public > 默认 > 私有)
Java中继承的注意事项
- Java中类只支持单继承,不支持多继承
错误范例:class A extends B, C { }
- Java中类支持多层继承多层继承示例代码:
-
package 包
- 包的概念包就是文件夹,用来管理类文件的
- 包的定义格式
package 包名; (多级包用.分开) 例如:package com.heima.demo;
- 带包编译&带包运行
带包编译:javac –d . 类名.java 例如:javac -d . com.heima.demo.HelloWorld.java
带包运行:java 包名+类名
例如:java com.heima.demo.HelloWorld
-
修饰符
-
重载
注意:方法的重载必须在一个类中,方法名、参数列表相同返回值不同不是方法重载(方法重载与返回值无关),方法重载返回值类型可以不相同
-
final
fianl关键字的作用
final代表最终的意思,可以修饰成员方法,成员变量,类 final修饰类、方法、变量的效果
fianl修饰类:该类不能被继承(不能有子类,但是可以有父类) final修饰方法:该方法不能被重写
final修饰变量:表明该变量是一个常量,不能再次赋值
final修饰的变量是基本类型时,指的是基本类型的数据值不能发生改变
final修饰的变量是引用类型时,指的是引用类型的地址值不能发生改变,但是地址里面的内容是可以发生改变的
final StringBuilder str = new StringBuilder("qwe");
System.out.println(str); //qwe
str.append("asd");
System.out.println(str); //qweasd
final Children ch = new Children();
ch.name="test";
System.out.println(ch.name); //test
ch.name="李淳罡";
System.out.println(ch.name); //李淳罡
-
static
static关键字是静态的意思,可以修饰【成员方法】,【成员变量】 static修饰的特点
- 被类的所有对象共享,这也是我们判断是否使用静态关键字的条件
- 可以通过类名调用当然,也可以通过对象名调用【推荐使用类名调用】
static的访问特点
非静态的成员方法
能访问静态的成员变量
能访问非静态的成员变量能访问静态的成员方法
能访问非静态的成员方法静态的成员方法
能访问静态的成员变量能访问静态的成员方法总结成一句话就是:
静态成员方法只能访问静态成员
-
多态
多态的概述(记忆)
- 什么是多态 同一个对象,在不同时刻表现出来的不同形态多态的前提
- 要有继承或实现关系要有方法的重写
- 要有父类引用指向子类对象
多态中的成员访问特点
成员变量 编译看父类,运行看父类
成员方法 编译看父类,运行看子类
public class Father{
int age = 30;
public void test1(){
System.out.println("父类test1");
}
}
public class Children extends Father {
int age = 20;
@Override
public void test1(){
System.out.println("子类test1");
}
}
public class Test {
public static void main(String[] args) {
Father fa = new Children();
System.out.println(fa.age);
fa.test1();
}
}
//-------------------result-----------------------------
30
子类test1
-
多态的好处和弊端
- 好处
提高程序的扩展性。定义方法时候,使用父类型作为参数,在使用的时候,使用具体的子类型参与操作
- 弊端
不能使用子类的特有成员
-
多态中的转型
向上转型:
从子到父:父类的引用指向子类对象
向下转型:
父类引用转为子类对象
package com.polym;
public class Animal {
public void eat(){
System.out.println("动物吃东西");
}
}
package com.polym;
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃东西");
}
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
package com.polym;
public class Test {
public static void main(String[] args) {
Animal ani = new Cat(); //向上转型
ani.eat();
//ani.catchMouse(); //报错
Cat cat = (Cat)ani; //向下转型
cat.catchMouse(); //调用猫类的特有方法
}
}
//--------------------------result---------------------------------
猫吃东西
猫抓老鼠
-
抽象类的概述
当我们在做子类共性功能抽取时,有些方法在父类中并没有具体的体现,这个时候就需要抽象类了! 在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类!
抽象类和抽象方法必须使用 abstract 关键字修饰
- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
- 抽象类不能实例化
抽象类如何实例化呢?参照多态的方式,通过子类对象实例化,这叫抽象类多态
3.抽象类的子类: 要么重写抽象类中的所有抽象方法 要么是抽象类
-
抽象类的成员特点
-
接口
接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。
Java中的接口更多的体现在对行为的抽象!
-
接口的成员特点
成员特点
默认修饰符: public static final
所以接口成员变量只能是常量
灰色的代表默认修饰符,两行代码等价
构造方法
接口没有构造方法,因为接口主要是对行为进行抽象的,是没有具体存在的
一个类如果没有父类,默认继承自Object类
public class runIm extends Object implements run {
public runIm() {
super(); //此处的super()访问的是Object类的构造方法
}
@Override
public void runTest() {
}
成员方法
默认修饰符:public abstract
所以接口的成员方法只能是抽象方法
类与类的关系
继承关系,只能单继承,但是可以多层继承 类与接口的关系
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
接口与接口的关系
继承关系,可以单继承,也可以多继承
-
接口组成更新
-
接口中默认方法
public interface ShowTest {
void show();
//实现类不要求强制重写
default void show2(){
System.out.println("接口默认方法show3");
}
}
public class ShowImplements implements ShowTest {
@Override
public void show(){
System.out.println("ShowImplements实现的show方法");
}
//接口默认方法可重写也可不重写
@Override
public void show2() {
System.out.println("ShowImplements实现的show2方法");
}
}
public static void main(String[] args) {
ShowTest st = new ShowImplements();
st.show();
st.show2();
}
/*
ShowImplements实现的show方法
ShowImplements实现的show2方法
*/
-
接口中静态方法
注意:具体类的静态方法可以通过类名或者对象名调用,但是接口的静态方法只能通过接口名称调用
public interface ShowTest {
void show();
static void show2(){
System.out.println("接口静态方法show2");
}
}
public class ShowImplements implements ShowTest {
@Override
public void show(){
System.out.println("ShowImplements实现的show方法");
}
}
public static void main(String[] args) {
ShowTest st = new ShowImplements();
st.show();
//st.show2(); //报错
//接口的静态方法只能通过接口名调用
ShowTest.show2();
}
/*
ShowImplements实现的show方法
接口静态方法show2
*/
-
接口中私有方法
public interface Inter {
default void show1() {
System.out.println("show1开始执行");
// System.out.println("初级工程师");
// System.out.println("中级工程师");
// System.out.println("高级工程师");
// show(); //非静态方法可以调用非静态方法也可以调用静态方法
method(); //非静态方法可以调用非静态方法也可以调用静态方法
System.out.println("show1结束执行");
}
default void show2() {
System.out.println("show2开始执行");
// System.out.println("初级工程师");
// System.out.println("中级工程师");
// System.out.println("高级工程师");
// show(); //非静态方法可以调用非静态方法也可以调用静态方法
method(); //非静态方法可以调用非静态方法也可以调用静态方法
System.out.println("show2结束执行");
}
private void show() {
System.out.println("初级工程师");
System.out.println("中级工程师");
System.out.println("高级工程师");
}
static void method1() {
System.out.println("method1开始执行");
// System.out.println("初级工程师");
// System.out.println("中级工程师");
// System.out.println("高级工程师");
// show();
method();
System.out.println("method1结束执行");
}
static void method2() {
System.out.println("method2开始执行");
// System.out.println("初级工程师");
// System.out.println("中级工程师");
// System.out.println("高级工程师");
method();
System.out.println("method2结束执行");
}
private static void method() {
System.out.println("初级工程师");
System.out.println("中级工程师");
System.out.println("高级工程师");
}
}
-
内部类
内部类概念:在一个类中定义一个类
访问特点:
- 内部类可以直接访问外部类的成员,包括私有
- 外部类要访问内部类的成员,必须创建对象
成员内部类
私有成员内部类,外界可以访问可以使用外部类对象调用本类方法没方法中再访问私有内部类
局部内部类
匿名内部类
匿名内部类的前提:存在一个类或者接口,这里的类可以是具体类也可以是抽象类
格式:
public class Anonymous {
public void method(){
//匿名内部类
Inter i = new Inter(){
@Override
public void show() {
System.out.println("匿名内部类");
}
};
i.show();
}
}
匿名内部类的本质:是一个继承了该类或者实现了该接口的子类匿名对象
-
Math(应用)
- Math类概述:Math 包含执行基本数字运算的方法
- Math中方法的调用方式:Math类中无构造方法,但内部的方法都是静态的,则可以通过 类名.进行调用
- Math类的常用方法
方法名 方法名 | 说明 |
public static int abs(int a) | 返回参数的绝对值 |
public static double ceil(double a) | 返回大于或等于参数的最小double值,等于一个整数 |
public static double floor(double a) | 返回小于或等于参数的最大double值,等于一个整数 |
public static int round(float a) | 按照四舍五入返回最接近参数的int |
public static int max(int a,int b) | 返回两个int值中的较大值 |
public static int min(int a,int b) | 返回两个int值中的较小值 |
public static double pow (double a,double b) | 返回a的b次幂的值 |
public static double random() | 返回值为double的正值,[0.0,1.0) |
获取0-99的随机整数
double random = Math.random();
System.out.println(random);
int ran = (int)(random*100);
System.out.println(ran);
-
System(应用)
System类的常用方法
方法名 | 说明 |
public static void exit(int status) | 终止当前运行的 Java 程序,非零表示异常终止 |
public static long currentTimeMillis() | 返回当前时间(以毫秒为单位) |
计算程序耗时
long start_time = System.currentTimeMillis();
for(int i=0;i<10000;i++){
System.out.println(i);
}
long end_time = System.currentTimeMillis();
System.out.println("共耗时:"+(end_time-start_time)+"毫秒");
-
Object类(应用)
Object类概述:Object 是类层次结构的根,每个类都可以将 Object 作为超类。所有类都直接或者间接的继承自该类,换句话说,该类所具备的方法,所有类都会有一份查看方法源码的方式
-
object toString方法
重写快捷键: Alt + Insert 选择toString
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
- public String toString()
- 返回对象的字符串表示形式。 一般来说,
toString
方法返回一个“toString
代表”这个对象的字符串。 结果应该是一个简明扼要的表达,容易让人阅读。 建议所有子类覆盖此方法。该
toString
类方法Object
返回一个由类的名称,其中所述对象是其实例,该符号字符`的字符串@
”,并且对象的哈希码的无符号的十六进制表示。 换句话说,这个方法返回一个等于下列值的字符串:getClass().getName() + '@' + Integer.toHexString(hashCode())
- 返回对象的字符串表示形式。 一般来说,
StudentNo stuNo = new StudentNo(1,"李淳风",25);
System.out.println(stuNo);
//重写toString方法
Student stu = new Student(1,"李淳风",25);
System.out.println(stu);
/* public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
*/
}
package com.ObjectStudy;
public class Student {
private int id;
private String name;
private int age;
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
...
}
-
Object类的equals方法
重写快捷键: Alt + Insert 选择equals 删除 hashCode
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (id != student.id) return false;
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
equals方法的作用
用于对象之间的比较,返回true和false的结果举例:s1.equals(s2); s1和s2是两个对象
重写equals方法的场景
不希望比较对象的地址值,想要结合对象属性进行比较的时候。
重写equals方法的方式
-
冒泡排序原理
冒泡排序概述:
一种排序的方式,对要进行排序的数据中相邻的数据进行两两比较,将较大的数据放在后面,依次对所有的数据进行操作,直至所有数据按要求完成排序如果有n个数据进行排序,总共需要比较n-1次,每一次比较完毕,下一次的比较就会少一个数据参与
数组冒泡排序
int[] arr = new int[10];
//生成随机长度为10的数组
for(int i=0; i< 10;i++){
int j = (int)(Math.random()*100);
arr[i] = j;
}
System.out.println(Arrays.toString(arr));
//冒泡排序
for(int i =1;i<arr.length;i++) {
for(int j=0;j<arr.length-i;j++) {
if(arr[j]>arr[j+1]) {
int temp = arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
System.out.println(Arrays.toString(arr));
//------------------------result------------------------
[75, 10, 7, 71, 47, 82, 87, 61, 23, 31]
[7, 10, 23, 31, 47, 61, 71, 75, 82, 87]
列表冒泡排序
ArrayList<Integer> arr = new ArrayList<Integer>();
//生成随机长度为10的列表
for(int i=0; i< 10;i++){
int j = (int)(Math.random()*100);
arr.add(j);
}
System.out.println(arr);
//冒泡排序
for(int i=arr.size()-1;i>0;i--){
for(int j=0;j<i;j++){
if(arr.get(j) > arr.get(j+1)){
int temp = arr.get(j+1);
arr.set(j+1, arr.get(j));
arr.set(j, temp);
}
}
}
System.out.println(arr);
//----------------result--------------
[47, 29, 83, 61, 54, 34, 6, 1, 35, 43]
[1, 6, 29, 34, 35, 43, 47, 54, 61, 83]
-
Arrays(应用)
Arrays的常用方法
方法名 | 说明 |
public static String toString(int[] a) | 返回指定数组的内容的字符串表示形式 |
public static void sort(int[] a) | 按照数字顺序排列指定的数组 |
-
工具类设计思想
- 构造方法用 private 修饰 (防止外界创建对象)
- 成员用 public static 修饰 (可以直接使用类名调用)
-
包装类
基本类型包装类
将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据
常用的操作之一:用于基本数据类型与字符串之间的转换 基本类型对应的包装类
基本数据类型 | 包装类 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
-
Integer类
Integer类概述:包装一个对象中的原始类型 int 的值
Integer类构造方法
方法名 | 说明 |
public Integer(int value) | 根据 int 值创建 Integer 对象(过时) |
public Integer(String s) | 根据 String 值创建 Integer 对象(过时) |
public static Integer valueOf(int i) | 返回表示指定的 int 值的 Integer 实例 |
public static Integer valueOf(String s) | 返回一个保存指定值的 Integer 对象 String |
-
int和String类型的相互转换
-
自动拆箱和自动装箱
自动装箱:把基本数据类型转换为对应的包装类类型
自动拆箱:把包装类类型转换为对应的基本数据类型
//装箱:把基本数据类型转换为对应的包装类类型
Integer i = Integer.valueOf(100);
//自动装箱
Integer ii = 100; //底层依然是: Integer.valueOf(100);
-
时间日期类
Date类
Date 代表了一个特定的时间,精确到毫秒
Date类构造方法
方法名 | 说明 |
public Date() | 分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒 |
public Date(long date) | 分配一个 Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数 |
Date类常用方法
方法名 | 说明 |
public long getTime() | 获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值 |
public void setTime(long time) | 设置时间,给的是毫秒值 |
-
SimpleDateFormat类
SimpleDateFormat是一个具体的类,用于以区域设置敏感的方式格式化和解析日期。
SimpleDateFormat类构造方法
方法名 | 说明 |
public SimpleDateFormat() | 构造一个SimpleDateFormat,使用默认模式和日期格式 |
public SimpleDateFormat(String pattern) | 构造一个SimpleDateFormat使用给定的模式和默认的日期格式 |
public static void main(String[] args) throws ParseException {
//格式化
Date time = new Date();
SimpleDateFormat tmFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String currentIime = tmFormat.format(time);
System.out.println(currentIime);
System.out.println("------------------------");
//解析
String strTime = "2019年12月15日 16:11:22";
SimpleDateFormat tmFormat2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date dd = tmFormat2.parse(strTime);
System.out.println(dd);
}
//-------------------------result----------
2019年10月20日 16:15:27
------------------------
Sun Dec 15 16:11:22 CST 2019
-
Calendar类
Calendar 为特定瞬间与一组日历字段之间的转换提供了一些方法,并为操作日历字段提供了一些方法 Calendar 提供了一个类方法 getInstance 用于获取这种类型的一般有用的对象。
该方法返回一个Calendar 对象。
其日历字段已使用当前日期和时间初始化:Calendar rightNow = Calendar.getInstance();
Calendar类常用方法
方法名 | 说明 |
public int get(int field) | 返回给定日历字段的值 |
public abstract void add(int field, int amount) | 根据日历的规则,将指定的时间量添加或减去给定的日历字段 |
public final void set(int year,int month,int date) | 设置当前日历的年月日 |
public static void main(String[] args) throws ParseException {
Calendar nowCa = Calendar.getInstance();
System.out.println(nowCa);
int year = nowCa.get(Calendar.YEAR);
int month = nowCa.get(Calendar.MONTH) + 1; //月是从0开始的,要获取当月需要加一
int date = nowCa.get(Calendar.DATE);
System.out.println(year + "年" + month + "月" + date + "日");
//日历的加减
//获取5年后的前3天
nowCa.add(Calendar.YEAR, 5);
nowCa.add(Calendar.DATE, -3);
year = nowCa.get(Calendar.YEAR);
month = nowCa.get(Calendar.MONTH) + 1; //月是从0开始的,要获取当月需要加一
date = nowCa.get(Calendar.DATE);
System.out.println(year + "年" + month + "月" + date + "日");
System.out.println("----------------------");
//设置日历值,设置日历值:2025年5月20日
nowCa.set(2025,4,20);
year = nowCa.get(Calendar.YEAR);
month = nowCa.get(Calendar.MONTH) + 1; //月是从0开始的,要获取当月需要加一,设置为设置值
date = nowCa.get(Calendar.DATE);
System.out.println(year + "年" + month + "月" + date + "日");
}
//--------------------------result----------------------
2019年10月20日
2024年10月17日
----------------------
2025年5月20日
-
二月天案例
获取任意一年的二月有多少天
思路:先获取该年的3月1日,往前推一天就是2月的最后一天也就是这月有多少天
public static void main(String[] args) throws ParseException {
Scanner scan = new Scanner(System.in);
while (true) {
System.out.println("请输入任意月份:");
int input = scan.nextInt();
Calendar nowCalendar = Calendar.getInstance();
//设置当前日历值为:输入年3月1日(日历值月份是从0开始)
nowCalendar.set(input, 2, 1);
//获取前一天
nowCalendar.add(Calendar.DATE, -1);
int dateNumber = nowCalendar.get(Calendar.DATE);
System.out.println("该年2月共有:" + dateNumber + "天");
}
}
//-------------------------result-----------------------
请输入任意月份:
2019
该年2月共有:28天
请输入任意月份:
2020
该年2月共有:29天
-
异常
异常就是程序出现了不正常的情况
-
try-catch方式处理异常
try-catch-finally执行顺序:先执行try语句,如果try语句中有return,则finally语句在try语句执行return之前执行,如果finally语句中有return则直接退出
public static void main(String[] args) throws IOException {
System.out.println(show());
}
public static int show(){
try {
System.out.println(1);
//制造异常
int index = "ab".getBytes()[3];
return 41;
}catch (Exception e){
System.out.println(e);
return 42;
}finally {
System.out.println(2);
//return 3;
}
}
/*
1
java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 2
2
42
*/
public static void main(String[] args) throws ParseException {
System.out.println("开始");
String a = null;
try {
a.split("");//java.lang.NullPointerException
} catch (NullPointerException e) {
System.out.println("空指针异常:");
e.printStackTrace();
}
System.out.println("结束");
/*开始
空指针异常:
java.lang.NullPointerException
at com.Test.Test.main(Test.java:12)
结束*/
}
public static void main(String[] args) throws ParseException {
System.out.println("开始");
int[] arr = {1,2,3};
try {
int a = arr[3]; //java.lang.ArrayIndexOutOfBoundsException: 3
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组索引越界:");
e.printStackTrace();
}
System.out.println("结束");
/*开始
数组索引越界:
java.lang.ArrayIndexOutOfBoundsException: 3
at com.Test.Test.main(Test.java:12)
结束*/
}
-
Throwable成员方法
常用方法
方法名 | 说明 |
public String getMessage() | 返回此 throwable 的详细消息字符串(返回错误原因) |
public String toString() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台(打印错误信息最全,一般采用此方法) |
-
throws方式处理异常
-
编译时异常和运行时异常的区别
-
自定义异常(应用)
throws 和throw的区别
public static void main(String[] args) {
int score = 105;
try {
ScoreTest.checkScore(score);
} catch (ScoreException e) {
e.printStackTrace();
}
}
public static void checkScore(int score) throws ScoreException {
if(score>=0 && score <=100){
System.out.println("分数正常");
}else{
throw new ScoreException("分数异常,给定分数不在0-100之间");
}
}
public class ScoreException extends Exception {
public ScoreException() {
}
public ScoreException(String message) {
super(message);
}
}
//--------------------------result-------------------------------
com.ThrowTest.ScoreException: 分数异常,给定分数不在0-100之间
at com.ThrowTest.ScoreTest.checkScore(ScoreTest.java:19)
at com.ThrowTest.ScoreTest.main(ScoreTest.java:9)