第一节
- 什么是JAVA
- Java 是一种面向对象的语言,它对对象中的类、对象、继承、封装、多态、接口、包等均有很好的支持。为了简单起见,Java 只支持类之间的单继承,但是可以使用接口来实现多继承。使用 Java 语言开发程序,需要采用面向对象的思想设计程序和编写代码。
- JAVA可以跨平台,只需要加装JVM就行。
2. 标识符由数字、字母、下划线(_)、及$组成 如:a12ghdg
注意:数字不能作为标识符的开始,如:1ac
3.关键字:具有特殊含义的标识符,例如:int、void、main、String....
4.用户自定义标识符:是由用户按标识符构成规则生成的非保留字的标识符,如 abc、name 就是一个标识符。
5.命名规则:
Java类的命名规则:类名首字母大写,如果由多个单词组合,则每个单词首字母大写(大驼峰命名法)
如:HelloWorld, Demo01
小驼峰命名法:首个单词字母小型,后面的单词首字母大写
如:helloWorld,dayMyYou
注意:java严格区分大小,如:name和Name表达的意思不一样
6.变量命名:
语法:变量类型 变量名字 赋值符号 值;
如以下例子:
int age; // 声明变量,不赋值
age = 32; // 声明变量之后赋值
String name = "大锤"; // 声明变量,赋值
age = 56;
name = "张三";// 修改变量值(重新赋值)
int 2num; // 非法命名
int n1, n2, n3, n4; // 批量命名(不推荐使用)
7.变量的作用域:
全局变量:
定义在方法(函数)和代码块之外的变量
局部变量:
定义在方法或者代码块之间的变量
(第一个大括号下定义的变量是全局变量,之后的大括号下定义的变量是局部变量)
例:
// 定义全局变量
int age; // 全局变量
String name = "大锤";
// 静态变量
static int number;
static double price = 1399.99;
public static void main(String[] args){
// 定义局部变量
int age;
if (true) {
String location;
}
第二节
- Java常量
常量是指在程序的整个运行过程中值保持不变的量。在这里要注意常量和常量值是不同的概念,常量值是常量的具体和直观的表现形式,常量是形式化的表现。通常在程序中既可以直接使用常量值,也可以使用常量。
- 常量命名规则:
- (1)常量名字应该全部大写
- (2)当常量名由多个单词组成时采用下划线分割,如:HTTP_CODE、HTTP_STATUS_CODE
- 成员常量和静态常量再定义同时必须初始化
- 定义常量,使用关键字final
(5)常量一旦被定义赋值,则不可再被修改
3.Java中的数据类型:
(1)基本数据类型(八种)
byte(字节型)、short(短整型)、int(整形)、long(长整型)、float(单精度浮点型)、double(双精度浮点型)
char(字符型)、boolean(布尔型)
(2)引用数据类型
除了基本数据类型,其他全部是引用数类型,如:String、数组等
类型名称 | 关键字 | 占用内存 |
字节型 | byte | 1 字节 |
短整型 | short | 2 字节 |
整型 | int | 4 字节 |
长整型 | long | 8 字节 |
单精度浮点型 | float | 4 字节 |
双精度浮点型 | double | 8 字节 |
字符型 | char | 2 字节 |
布尔型 | boolean | 1 字节 |
例子:
// 字节型
byte by = 127;
// System.out.println((byte) (by + 1));
// 短整型
short sh = 56;
// 整形
int num = 78946;
// 长整型,注意: 需要早长整型末尾添加L或者l
long number = 56L;
// 单精度浮点型, 注意: 需要早长整型末尾添加F或者f
float fl = 3.14F;
float fl1 = 3.1415888888879874243246564564561129f; // 精度丢失
System.out.println(fl1);
// 双精度浮点型,java中小数默认是double类型
double db = 3.14159;
// 字符型, 字符型的值使用单引号引起来,当值为整形时不需要单引号
char ch1 = 3;
char ch2 = 'a';
char ch3 = 97;
System.out.println(ch1);
System.out.println(ch3);
// 布尔值类型,注意:Java中布尔值类型只有true和false两个值
boolean bool1 = true;
boolean bool2 = false;
// null类型
String str = null;
System.out.println(name);
// int a = null; 报错
第三节
一、Java数据类型转换
1.隐式转换(自动类型转换)
如果以下 2 个条件都满足,那么将一种类型的数据赋给另外一种类型变量的时,将执行自动类型转换(automatic type conversion)。
(1)、两种数据类型彼此兼容
(2)、目标类型的取值范围大于源数据类型(低级类型数据转换成高级类型数据)
(3)、数值型数据的转换:byte→short→int→long→float→double。
(4)、字符型转换为整型:char→int。
注意:char 类型比较特殊,char 自动转换成 int、long、float 和 double,但 byte 和 short 不能自动转换为 char,而且 char 也不能自动转换为 byte 或 short。
例子:
byte b1 = 25;
// 小类型数据转为大类型数据(自动转换)
short s1 = b1;
- 显式转换(强制类型转换)
大类型数据转为小类型数据时需要强制转换(类型强转)
小类型 变量名 = (需要转换的类型) 大类型;
注意:大类型数据转为小类型数据有可能会造成数据进度丢失和溢出
short类型与char类互相转化需要强制转换
注意:两种数据类型彼此兼容,否则不能互相转换
基本数据类型不能与引用数据类型转换
例子:
short s2 = 654;
byte b2 = (byte) s2;
short s3 = 97;
char ch1 = (char) s3;
char ch2 = 'A';
short s4 = (short) ch2;
正在上传…重新上传取消正在上传…重新上传取消
第四节
一、Java算术运算符
- 一元运算符
算术一元运算一共有 3 个,分别是 -、++ 和 --。
++i和i++的区别:
++i是先自增再赋值
i++是先赋值再自增
--同上
例子:
int num4;
num4 = num3 ++; // 先将 num3 赋值给num4,然后num3再自增 1
int num5 = 25;
int num6;
num6 = ++ num5; // 先num5自增,然后再将自增之后的值赋值给 num6
2、二元运算符
Java 语言中算术运算符的功能是进行算术运算,除了经常使用的加(+)、减(-)、乘(*)和除(\)外,还有取模运算(%)。加(+)、减(-)、乘(*)、除(\)和我们平常接触的数学运算具有相同的含义。
运 算 符 | 名 称 | 说 明 | 例 子 |
+ | 加 | 求 a 加 b 的和,还可用于 String 类型,进行字符串连接操作 | a + b |
- | 减 | 求 a 减 b 的差 | a - b |
* | 乘 | 求 a 乘以 b 的积 | a * b |
/ | 除 | 求 a 除以 b 的商 | a / b |
% | 取余 | 求 a 除以 b 的余数 | a % b |
Java 语言中算术运算符的功能是进行算术运算,
除了经常使用的加(+)、减(-)、乘(`*`)和除(\)外,
还有取模运算(%)。加(+)、减(-)、乘(`*`)、除(\)
和我们平常接触的数学运算具有相同的含义
二、Java赋值运算符
java中赋值运算符:
=:赋值符号
+=:如, num += 2; -----> 本质:num = num + 2;
-=: 如, num -= 2; -----> 本质:num = num - 2;
*=: 如, num *= 2; -----> 本质:num = num * 2;
/=: 如, num /= 2; -----> 本质:num = num / 2;
%=: 如, num %= 2; -----> 本质:num = num % 2;
三、Java逻辑运算符
java中逻辑运算符:
与、或、非
&&(短路与):如:a && b, 如果ab全部为true则结果为true,否则为false
||(短路或):如:a || b, a或者b有一个为true,或者ab均为true,则为true,否则为false
!:a为true,则结果为false,a为false,则结果为true
&& 与 & 区别:如果 a 为 false,则不计算 b(因为不论 b 为何值,结果都为 false)
|| 与 | 区别:如果 a 为 true,则不计算 b(因为不论 b 为何值,结果都为 true)
第五节
一、关系运算符
* ==:对等于
* !=:不等于
* >:大于
* <:小于
* >=:大于等于
* <=:小于等于
*
* 注意:关系运算符的结果为布尔值类型
equals(obj)方法和 == 的区别:
* equals方法比较的是两个对象的内容是否相等
* == 比较的是两个对象再内存中存放的地址是否为同一个
二、java扫描器
用户从控制台输入数据,后台Java程序接收
Scanner scan = new Scanner(System.in);// 创建扫描器对象
int age = scan.nextInt();//给输入项赋值
next()与nextLine()方法的区别:
* 1、当遇到空格或者回车的时候 next()方法停止读取
* 2、当遇到回车的时候 nextLine()方法停止读取,读取整行数据
- 位移运算符
运算符 | 含义 | 实例 | 结果 |
» | 右移位运算符 | 8»1 | 4 |
« | 左移位运算符 | 9«2 | 36 |
位移运算符用来将操作数向某个方向(向左或者右)移动指定的二进制位数。
例子:
8>>1
0000 1000 //8
0000 0100 //4
第六节
一、if else 语句
选择结构(也叫分支结构)解决了顺序结构不能判断的缺点,可以根据一个条件判断执行哪些语句块。选择结构适合于带有逻辑或关系比较等条件判断的计算。例如,判断是否到下班时间,判断两个数的大小等。
1、单分支结构:
if () {
}
2、双分支结构
if语句:
if (条件表达式) {
// 条件为true执行
// 代码块
} else {
// 条件为false执行
}
3、多分支结构:
if () {
}else if () {
}else if () {
}....{
}else{
// 最后的else语句可要可不要
}
4、if嵌套
if(boolean){
if(boolean){
....
}
}else{
if(boolean){
....
}
}
5、三木运算语法(本质:还是if语句):
条件表达式 ? 表达式1 :表达式2
当表达式结果true,执行表达式1,否则执行表达式2
条件表达式 ? (条件表达式1 ? 表达式1 :表达式2) :(条件表达式2 ? 表达式1 :表达式2)
二、switch case语句
switch 语句是 Java 的多路分支语句。它提供了一种基于一个表达式的值来使程序执行不同部分的简单方法。因此,它提供了一个比一系列 if-else-if 语句更好的选择。
switch(表达式) {
case 值1:
语句块1;
break;
case 值2:
语句块2;
break;
…
case 值n:
语句块n;
break;
default:
语句块n+1;
break;
}
- while 和 do while 循环
1、while 语句是 Java 最基本的循环语句,是一种先判断的循环结构,可以在一定条件下重复执行一段代码。该语句需要判断一个测试条件,如果该条件为真,则执行循环语句(循环语句可以是一条或多条),否则跳出循环。
while(条件表达式) {
语句块;
}
- do-while 循环语句也是 Java 中运用广泛的循环语句,它由循环条件和循环体组成,但它与 while 语句略有不同。do-while 循环语句的特点是先执行循环体,然后判断循环条件是否成立。
do {
语句块;
}while(条件表达式);
3、while循环与do...while循环的区别:
(1)while是先判断后执行,do...while循环是先执行然后再判断
(2)do...while循环至少执行一次
while循环与do...while的特点:都是循环执行某一语句,循环次数素不固定
- for循环
for 语句是应用最广泛、功能最强的一种循环语句。大部分情况下,for 循环可以代替 while 循环、do while 循环。
for 语句是一种在程序执行前就要先判断条件表达式是否为真的循环语句。假如条件表达式的结果为假,那么它的循环语句根本不会执行。for 语句通常使用在知道循环次数的循环中。for 语句语法格式如下所示。
for(表达式1; 表达式2; 表达式3) {
语句块;
}
循环嵌套
如果循环嵌套层数超过三层,那么一定是逻辑出了问题
for () {
while (){
do{
for () {
}
}while ();
}
}
六、foreach 语句的用法
foreach语法:
for(迭代变量类型 变量的名字 :需要遍历(迭代)的对象){
语句块;
}
foreach 循环语句是 Java 1.5 的新特征之一,在遍历数组、集合方面,foreach 为开发者提供了极大的方便。foreach 循环语句是 for 语句的特殊简化版本,主要用于执行遍历功能的循环。
break语句:作用:结束当前循环
continue:结束本次循环,强制进入下一次循环
七、方法的定义和调用
首先方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
返回值类型 :方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。
方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
方法体:方法体包含具体的语句,定义该方法的功能。
定义方法的语法:
* 修饰符 返回值类型 方法名(参数1,参数2...) { 方法体... }
return关键字的作用:1、结束方法的执行。2、将方法的执行结果返回给调用者
方法(函数)的类型:
1、无参无返回值
修饰符 void 方法名(){ 方法体 }
2、无参有返回值
修饰符 返回值类型 方法名(){ 方法体}
3、有参无返回值
修饰符 void 方法名(参数1, 参数2,....){ 方法体}
4、有参有返回值
修饰符 返回值类型 方法名(参数1, 参数2,....){ 方法体}
方法调用
1、通过 对象.方法名字(参数)
2、类名.方法(参数)
3、方法(参数)
方法重载:
重载就是在一个类中,有相同的函数名称,但参数列表不相同的方法。
注意:
方法重载只与方法名字和参数列表有关,与方法返回值类型无关
方法签名:方法名字 + 参数列表
什么是程序?
答:程序 = 算法 + 数据结构
可变参数必须位于参数列表的最后一个
/*public String fun3(long... longs, String str, int num){
return null;
}*/
- 递归
是一种直接或者间接地调用自身的算法。在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解。
递归算法:在函数或子过程的内部,直接或者间接地调用自己的算法。 递归算法的实质:是把问题转化为规模缩小了的同类问题的子问题。然后递归调用函数(或过程)来表示问题的解。
递归算法解决问题的特点: (1) 递归就是在过程或函数里调用自身。 (2) 在使用递增归策略时,必须有一个明确的递归结束条件,称为递归出口。 (3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。 (4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。
递归的两个条件:
1、可以通过递归调用来缩小问题规模,且新问题与原问题有着相同的形式。(自身调用)
2、存在一种简单情境,可以使递归在简单情境下退出。(递归出口)
递归三要素:
1、一定有一种可以退出程序的情况;
2、总是在尝试将一个问题化简到更小的规模
3、父问题与子问题不能有重叠的部分
九、数组
1、数组以及数组的声明和创建
数组定义:
用来存放相同类型的一组数据
数组下标从0开始,对数组元素进行操作是通过数组的下标(索引),数组的最后一个元素的下表为:数组长度-1
数组一旦被创建,则数组的长度不可被修改
语法:
静态创建数组
数据类型[] 数组名 = {值1,值2....}
数据类型 数组名[] = {值1,值2....}
动态创建数组
数据类型[] 数组名 = new 数据类型[数组长度]
数据类型 数组名[] = new 数据类型[数组长度]
int[ ] arr;
或者
int arr[ ];
int[ ] arr = new int[ 数组长度 ];
2、数组三种初始化
静态初始化
除了用new关键字来产生数组以外,还可以直接在定义数组的同时就为数组元素分配空间并赋值。
// 静态初始化基本类型数组
int[] a = {1, 2, 3};
动态初始化
数组定义与为数组元素分配空间并赋值的操作分开进行
int[] a1 = new int[2];// 动态初始化元素,先分配空间
a1[0] = 1;// 给数组元素赋值
a1[2] = 2;
数组的默认初始化
数组是引用类型,他的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化
3、下标越界异常
数组的边界:
数组的下标合法区间为:`[0,length-1]`,如果在这个范围之外将会报错,这种情况称为数组下标越界
java.lang.ArrayIndexOutOfBoundsException: -1
数组下标越界异常
参数数组下标越界异常的原因:
操作数组元素的索引超出数组界限
随机数:
* 1、Random random = new Random();
* 生成指定范围内的随机数 random.nextInt(10)
*
* 2、double random = Math.random();
* 生成随机数的范围 0.0-1.0,但是永远到不了 1
遍历数组:
遍历数组的意思就是将数组的元素逐个取出来,通常我们使用循环进行遍历。
九、二维数组
java中使用 [][] 来定义二维数组,定义数组时也可同时初始化。
两种初始化形式:
格式1、动态初始化
数据类型 数组名[][] = new 数据类型[m][n]
数据类型[][] 数组名 = new 数据类型[m][n]
数据类型[] 数组名[] = new 数据类型[m][n]
举例:
int [][] arr = new int[5][3]; //也可以理解为“5行3例”。
格式2、 静态初始化
数据类型[][] 数组名 = {{元素1,元素2....},{元素1,元素2....},{元素1,元素2....}.....};
举例:
int[][] arr = {{22, 15, 32, 20, 18}, {12, 21, 25, 19, 33}, {14, 58, 34, 24, 66}}。
二维数组的遍历:
public static void main(String[] args) {
int[][] arr = {{22, 15, 32, 20, 18}, {12, 21, 25, 19, 33}, {14, 58, 34, 24, 66}};
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
System.out.println(arr[i][j]);
}
}
}
第七节
一、Arrays类
Arrays类具有以下常用的功能:
给数组赋值:通过调用fill方法。
对数组进行排序:通过sort方法。
比较数组:通过equals方法比较数组中元素的值是否相等。
查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作。
将数组转为字符串输出:通过toString方法实现
- System.arraycopy(浅拷贝)
System.arraycopy(arr, start, dist, index, length)
- Arrays.copyOf(浅拷贝)
dest = Arrays.copyOf(src, 2); // Arrays.copyOf src为原数组,2为复制的位数
3、、Object.clone**
```java
dest = (int[]) src.clone();//使用clone创建
```
dest为目的数组,src为原数组,clone复制实现数组全部复制。
> **注:**clone()比较特殊,对于对象而言,它是深拷贝,但是对于数组而言,它是浅拷贝。
**对象拷贝**
首先讲一下对象的拷贝,它是深拷贝,大家可以用对象去测试一下。下面我们看一下它的源代码:
```java
protected native Object clone() throws CloneNotSupportedException;
```
这里也有native关键字,所以也是底层的c语言实现的。
4、Arrays.copyOfRange
dest = Arrays.copyOfRange(src, 1, 3);//Arrays.copyOfRange
src为原数组,1为起始下标,3为结束下标
- 数组扩容与缩容:
数组扩容与缩容的实质:就是创建一个新的数组,新数组的长度比原来的数组(大,扩容,小,缩容)
二、排序算法
1、十种常见排序算法可以分为两大类:
比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。
2、算法复杂度
稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。
3、案例
/**
* 给数组赋值:通过调用fill方法。
*/
int arr1[] = new int[12000];
// 给数组元素复制
Arrays.fill(arr1, 99);
System.out.println(Arrays.toString(arr1));
/**
* 对数组进行排序:通过sort方法。
*/
int[] arr = {56, 78, 2, 0, 45, 48, 3, 96, 108, 1};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
/**
* 查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作。
* Arrays.binarySearch(arr, 96);该方法的返回值为查找到的元素下标
* 注意使用该方法的前提是数组必须要排好序
*/
int result = Arrays.binarySearch(arr, 9999);
System.out.println(result);
/**
* Arrays.equals(b1, b2)
* 比较数组:通过equals方法比较数组中元素的值是否相等。
*/
byte[] b1 = {1, 12};
byte[] b2 = {2, 56};
byte[] b3 = {1, 12};
// 比较两个数组元素是否相等
System.out.println(Arrays.equals(b1, b2));
System.out.println(Arrays.equals(b1, b3));
4、冒泡排序
例如:每次 排序都将大的数放到最后
- 算法描述
1、比较相邻的元素。如果第一个比第二个大,就交换它们两个;
2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
3、针对所有的元素重复以上的步骤,除了最后一个;
4、重复步骤1~3,直到排序完成。
5、稀疏数组
稀疏数组介绍:
当一个数组中大部分元素为0时,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
稀疏数组的处理方式是:
(1) 记录数组一共有几行几列,有多少个不同的值。
(2) 把具体有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模。
稀疏数组定义:
稀疏数组可以看做是普通数组的压缩,但是这里说的普通数组是值无效数据量远大于有效数据量的数组。
案例:
public static void main(String[] args) {
int[][] ar = new int[5][6];
ar[0][4] = 1;
ar[1][1] = 89;
ar[3][0] = 25;
ar[4][5] = 2022;
// 打印原数组
for (int[] arr : ar) {
for (int i : arr) {
System.out.print(i + "\t");
}
System.out.println();
}
System.out.println("**************************************************");
// 打印稀疏数组
//int[][] array = sparse(ar);
for (int[] arr : sparse(ar) /*array*/) {
for (int i : arr) {
System.out.print(i + "\t");
}
System.out.println();
}
System.out.println("**************************************************");
// 还原二维数组
/**
* parseToPlanar(sparse(ar))本质:
* int[][] a = sparse(ar);
* int[][] b = parseToPlanar(a);
*/
for (int[] arr : parseToPlanar(sparse(ar)) /*b*/) {
for (int i : arr) {
System.out.print(i + "\t");
}
System.out.println();
}
三、面对对象
类是对象的模板,对象是类的具体的实例
面向过程思想:
1、 步骤清晰简单,第一步要做什么,第二步要做什么……
2、 面向过程适合处理一些较为简单的问题
面向对象思想:
1、 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考,最后,才对某个分类 下的细节进行面向过程的思索。
2、 面向对象适合处理复杂的问题,适合处理需要多人协作的问题
面向过程的结构化程序设计:
结构化程序设计的弊端:
1、缺乏对数据的封装
2、数据与方法(操作数据)的分离
什么是面向对象:
面向对象的本质就是:以类的方式组织代码,以对象的组织(封装)数据。
什么是抽象的数据类型:
所谓抽象数据类型可以理解为:将不同类型的数据的集合组成一个整体,用来描述一种新的事务。如:对象类型数据
什么是类?什么是对象?
1、现实世界是由很多很多对象组成的
基于对象抽出了类
2、对象:真实存在的单个的个体
类:类型/类别,代表一类个体
3、类中可以包含:
3.1、所有对象所共有的属性/特征------------成员变量
3.2、所有对象所共有的行为-----------------方法
4、一个类可以创建多个对象
同一类型所创建的对象,结构相同,数据不同
面向对象的三大特征:
封装、继承、多态
补充:
1、OOA:面向对象分析方法,是确定需求或者业务的角度,按照面向对象的思想来分析业务。
2、OOD:面向对象设计方法是OO方法中一个中间过渡环节。其主要作用是对OOA分析的结果作进一步的规范化整理,以便能够被OOP直接接受。
3、OOP:面向对象程序设计作为一种新方法,其本质是以建立模型体现出来的抽象思维过程和面向对象的方法。
四、类与对象的创建
创建对象语法:
* 数据类型 引用类型变量 指向(引用) new关键字 对象
* Student zs = new Student();
定义一个类:
定义类的成员变量:
1、类的定义包括“成员变量”的定义和“方法”的定义,其中“成员变量”用于描述对象 共同的数据结构,“方法”则是所有对象共同的 行为。
2、Java语言中,类的成员变量的定义可以使用如下的语法:
修饰符 class 类名 {
成员变量类型 变量名;
………
}
3、对象创建后,其成员变量可以按照默认的方式初始化,初始化对象成员变量时,其默认值的规则如下表所示:
成员变量类型 | 默认初始值 |
数值类型(byte、short、int、long、float、double) | 0 |
boolean类型 | false |
char类型 | /u0000 |
引用类型 | null |
定义类的方法:
类中除了定义成员变量,还可以定义方法,用于描述对象的行为,封装对象的功能,Java语言中,可以按照如下方式定义类中的方法:
class 类名 {
修饰符 返回值类型 方法名(参数列表){
方法体………
}
……………
}
创建并且使用对象:
使用new关键字创建对象:
类定义完成之后,可以使用new关键字创建对象,创建对象的过程通常称为实例化对象,new的运算语法为:
new 类名();
如:new JFrame(); //可以创建一个窗体对象
第八节
- 构造器和构造方法
构造方法是在类中定义的方法,不同于其他的方法,构造方法的定义有如下两点规则:
1)构造方法的名称必须与类名完全相同。
2)构造方法没有返回值,连void关键字有没有
构造方法(构造函数):
每一个Java类必须包含构造方法,如果程序员没有手动添加构造方法,则编译器会在编译时添加一个默认的
无参构造方法,关于构造方法的特点:1、构造方法的方法名字必须与类名完全相同(包括大小写必须相同),2、
构造方法没有任何返回值,连void关键字也没有。
构造方法的语法:
修饰符 类名(参数){
方法体....
}
构造方法的作用:用于创建类的对象(实例化对象),还可以初始化成员变量的初始值
注意:当我们手动添加构造器(构造方法)之后,编译器将不在为我们添加默认的无参构造器
构造方法的重载:
为了使用方便,可以对一个类定义多个构造方法,这些构造方法都有相同的名称,但是方法的参数列表不同,称为构造方法的重载。
一个构造方法可以通过this关键字调用另外一个重载的构造方法。
this关键字的使用:
this关键字用在方法体中,用于指向调用该方法的当前对象,简单来说,那个对象调用方法,this就指的是那个对象,严格来讲在方法中需要通过this关键字指明当前对象。
当我们在方法中不添加this关键字时,编译器会默认补上this关键字
- Java内存分析
正在上传…重新上传取消正在上传…重新上传取消
- 访问控制修饰符
1、public和private
private修饰的成员变量和方法仅仅只能在本类中访问调用。
public修饰的成员变量和方法可以在任何地方调用,public修饰的内容是对外提供可以被调用的功能,需要相对稳定,private修饰的内容是对类实现的封装,如果“公开”会增加维护的成本。
2、 protected和默认访问控制
1)用protected修饰的成员变量和方法可以被子类及同一个包中的类使用。
2)默认的访问控制即不书写任何访问修饰符,默认访问控制的成员变量和方法可以被同一个包中的类调用。
3、访问控制修饰类
1)对于类的修饰可以使用public和默认的方式,public修饰的类可以被任意一个类使用,默认方法控制的类只能被同包中的类使用。
2)protected和private可以用于修饰内部类
五、封装
封装,简单的说就是该露的露,该藏的藏。我们在设计程序是要追求“高内聚,低耦合”,其中,高内聚指的是类的内部数据操作细节由自己完成,不允许外部干涉。低耦合指的是仅暴露少量的方法给外部调用(使用get/set方法)。
封装(对数据的隐藏),通常来说,应禁止直接访问应该对象中数据的实际表示,而是应该通过操作接口来访问,这种称为信息隐藏。
封装的意义:
1、对外提供可调用的,稳定的功能。
2、封装容易变化的,具体的细节,外界不可访问,这样封装的意义在于:
a. 降低代码出错的可能性,便于维护。
b. 当内部的实现细节改变时,只要保证对外的功能定义不变,其他的模块就不会因此而受到牵连。
封装的核心:属性私有化,行为(方法)公开化
- 继承
1、通过extends关键字可以实现类的继承。
2、子类可以继承父类的成员变量及成员方法,同时也可以定义自己的成员变量和成员方法。
3、Java语言不支持多重继承,一个类只能继承一个父类,但是一个父类可以有多个子类。
七、关于super 与 this 关键字的对比(区别):
1. super(参数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句)。
2. this(参数):调用本类中另一种形成的构造函数(应该为构造函数中的第一条语句)。
3. super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参)。
4. this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)
5、调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。
6、super()和this()类似,区别是,super()从子类中调用父类的构造方法,this()在同一类内调用其它方法。
7、super()和this()均需放在构造方法内第一行。
8、尽管可以用this调用一个构造器,但却不能调用两个。
9、this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
10、 this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
11、 从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。
八、方法的重写(Override):
1、发生在父子类中,方法名称相同,参数列表相同,方法体不同
2、重写方法被调用时,看对象的类型
3、遵循"两同两小一大"原则:------------了解
3.1、两同:
3.1.1、方法名称相同
3.1.2、参数列表相同
3.2、两小:
3.2.1、派生类方法的返回值类型小于或等于超类方法的
a、void时,必须相同
b、基本数据类型时,必须相同
c、引用数据类型时,小于或等于
3.2.2、派生类方法抛出的异常小于或等于超类方法的
3.3、一大:
3.3.1、派生类方法的访问权限大于或等于超类方法的
重写与重载的区别:
1、重写(Override):
1.1、发生在父子类中,方法名相同,参数列表相同,方法体不同
1.2、"运行期绑定",看对象的类型绑定方法
2、重载(Overload):
2.1、发生在一个类中,方法名相同,参数列表不同,方法体不同
2.2、"编译期绑定",看参数/引用的类型绑定方法
补充:
编译期:.java源文件,经过编译,生成.class字节码文件
运行期:JVM加载.class并运行.class
编译错误:只是检查语法
第九节
一、多态
多态指的是同一方法可以根据发送对象的不同而采用多种不同的行为方式。
一个对象的实际类型是确定的,但是可以指向对象的引用的类型有很多。
多态存在的条件:
1、 有继承关系
2、 子类重写父类的方法
3、 父类引用指向子类对象
多态的意义:
1、行为的多态(所有抽象方法都是多态的)
2、对象的多态(所有对象都是多态的)
多态的表现形式:
1、重写:根据对象的不同来表现多态
2、重载:根据参数的不同来表现多态
注:多态是方法的多态性,属性没有多态性。
- instanceof 和类型转换
instanceof 是 Java 的一个二元操作符,类似于 ==,>,< 等操作符。
instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例(实例指的是“类”在实例化之后叫做一个“实例”。实例化:通常把用类创建对象的过程称为实例化),返回 boolean 的数据类型。
向上造型:
1)超类型的引用指向派生类的对象
2)能点出来什么,看引用的类型
向下造型:(容易出现类型转换异常)
1)派生类的引用指向超类对象
2)向下造型需要进行强转
3)能点出来什么,看引用的类型
类型转换:
1、向上造型:子类对象指向父的引用
2、向下造型:父类对象指向子类引用
能访问什么看引用类型
三、static和final关键字
(1)Static块属于类的代码块,在类加载期间指向代码块,只执行一次,可以用来在软件中加载静态资源。
* 语法:
* static {
* 静态代码块
* }
1、用static修饰的成员变量不属于对象的数据结构,属于类的数据结构。
2、static变量是属于类的变量,通常可以通过类名来引用static成员。
3、static成员变量和类的信息一起存储在方法区,而不是在堆中,一个类的static变量只有一份,无论这个类创建了多少个对象。
(2)1、final关键字修饰成员变量,表示变量不可被改变。
2、final修饰成员变量的两种方式初始化:
a. 声明的同时初始化
b. 构造函数中初始化
3、final关键字也可以修饰局部变量,使用之前初始化即可
final关键字修饰的方法不可被重写。
使一个方法不能被重写的意义在于:防止子类在定义新方法使造成“不间意”重写。
1、static final修饰的成员变量称为常量,必须声明同时初始化,不可被改变。
2、static final常量会在编译期被替换,
四、抽象类(abstract)
抽象类描述:(在Java语言中使用abstract class来定义抽象类)
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
在Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
抽象方法:
1、由abstract修饰
2、只有方法的定义,没有具体的实现(连{ }都没有)
如果一个方法使用 abstract 来修饰,则说明该方法是抽象方法,抽象方法只有声明没有实现。需要注意的是 abstract 关键字只能用于普通方法,不能用于 static 方法或者构造方法中。
抽象方法的 3 个特征如下:
1)抽象方法没有方法体
2)抽象方法必须存在于抽象类中
3)子类重写父类时,必须重写父类所有的抽象方法
注意:在使用 abstract 关键字修饰抽象方法时不能使用 private 修饰,因为抽象方法必须被子类重写,而如果使用了 private 声明,则子类是无法重写的。
抽象类:
1、由abstract修饰
2、包含抽象方法的类必须是抽象类
不包含抽象方法的类也可以声明为抽象类------我乐意
3、抽象类不能被实例化
4、抽象类是需要被继承的,派生类:
4.1、重写所有抽象方法--------常用
4.2、也声明为抽象类----------一般不这么做
5、抽象类的意义:
5.1、封装派生类所共有的属性和行为---------代码复用
5.2、给所有派生类提供统一的类型-----------向上造型
5.3、可以包含抽象方法,为所有派生类提供统一的入口
派生类的具体行为不同,但入口是一致的
设计规则:
1、将派生类所共有的属性和行为,抽到超类中--------抽共性
2、所有派生类的行为都一样,设计普通方法
所有派生类的行为都不一样,设计为抽象方法
五、接口(Interface)
接口中不能有构造器
在接口中定义的变量默认为 public final static修饰
接口中的方法必须全部是抽象方法
public abstract Demo01();abstract关键字不能修饰构造器
抽象方法使用abstract关键字修饰:
* 抽象方法没有方法体,连{}也没有
*
* 抽象方法允许有方法重载
*
* 注意:如果一个类包含抽象方法,那么该类必须声明为抽象类
访问接口中的常量 实现类名.常量名
访问接口中的常量 接口名.常量名
接口不能被实例化
接口中不允许有静态代码块
JDK1.8以后可以允许有静态方法和方法体
接口与类的区别:
1)接口不能用于实例化对象。
2)接口没有构造方法。
3)接口中所有的方法必须是抽象方法。
4)接口不能包含成员变量,除了 static 和 final 变量。
5)接口不是被类继承了,而是要被类实现。
6)接口支持多继承(接口不能继承类,接口只能继承接口)。
接口特性:
1)接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
2)接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
3)接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
抽象类和接口的区别:
1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
六、内部类
java内部类的几种类型:成员内部类,静态内部类,方法内部类,匿名内部类。
创建内部类的对象 语法: 外部类.内部类 = 外部类对象.new 内部类()
定义方法内部类, 不能对方法内部类使用访问修饰符和static关键字
定义成员内部类
语法:
修饰符 class关键字 类名{类体}
内部类的作用通常用于服务外部类
public static double salary; 内部类不允许定义静态的变量
public static void b(){ } 内部类不允许定义静态的方法
需要注意:由于方法内部类不能在外部类的方法以外的地方使用,因此方法内部类不能使用访问控制符和 static 修饰符。
七、枚举
枚举是一个被命名的整型常数的集合,用于声明一组带标识符的常数。枚举在曰常生活中很常见,例如一个人的性别只能是“男”或者“女”,一周的星期只能是 7 天中的一个等。类似这种当一个变量有几种固定可能的取值时,就可以将它定义为枚举类型。
在 JDK 1.5 之前没有枚举类型,那时候一般用接口常量来替代。而使用 Java 枚举类型 enum 可以更贴近地表示这种常量。
Java 中的每一个枚举都继承自 java.lang.Enum 类。当定义一个枚举类型时,每一个枚举类型成员都可以看作是 Enum 类的实例,这些枚举成员默认都被 final、public, static 修饰,当使用枚举类型成员时,直接使用枚举名称调用成员即可。
所有枚举实例都可以调用 Enum 类的方法
Java 为枚举类型提供了一些内置的方法,同时枚举常量也可以有自己的方法。此时要注意必须在枚举实例的最后一个成员后添加分号,而且必须先定义枚举实例。
Java 中的 enum 还可以跟 Class 类一样覆盖基类的方法。下面示例代码创建的 Color 枚举类型覆盖了 toString() 方法。
protected修饰的属性和方法只能在本类和同包以及子类中访问
Java SE
一、String
1、分配一个新字符串,该字符串包含字符数组参数的子数组中的字符。
offset参数是子数组第一个字符的索引,count参数指定子数组的长度。
复制子数组的内容;字符数组的后续修改不会影响新创建的字符串。
2、分配一个新字符串,该字符串包含来自Unicode码点数组参数子数组的字符。
offset参数是子数组第一个编码点的索引,count参数指定子数组的长度。
子数组的内容被转换为字符;int数组的后续修改不会影响新创建的字符串。
3、将字符串转为int类型数据
注意:
将字符串转为int类型的值前提是字符内容必须是纯数字
使用包装类进行转换
4、Java中使用 “+” 运算符进行连接对程序的效率有很大的影响!
5、变量名.toUpperCase()和变量名.toLowerCase()
Jana中使用这两个方法对数组或字符串进行大小写转换。
- subsString
此方法是对字符串进行截取。使用方法是:变量名.subsString(截取的起始位置,结束位置)。
- date类
date类简介
获取系统当前时间
如果使用 DateFormat 类格式化日期/时间并不能满足要求,
那么就需要使用 DateFormat 类的子类——SimpleDateFormat。
/**
* Calendar 类
*/
// Calendar 类对象
Calendar cl = Calendar.getInstance();
// 获取一星期的第一天。根据不同的国家地区,返回不同的值
System.out.println(cl.getFirstDayOfWeek());
int year = cl.get(Calendar.YEAR); // 获取当前年份
System.out.println("现在是" + year + "年");
三、Math
1\Math类中常见的两个静态常量E、PI
System.out.println("自然对数:" + Math.E);
System.out.println("圆周率:" + Math.PI);
2、math类中获取最大值和最小值
int a = 56;
int b = 23;
System.out.println("最大值为:" + Math.max(a, b));
System.out.println("最小值:" + Math.min(a, b));
四、Random类
Random 类提供了丰富的随机数生成方法,可以产生 boolean、int、long、float、byte
数组以及 double 类型的随机数,这是它与 Math.random() 方法最大的不同之处。random()
方法只能产生 double 类型的 0~1 的随机数。
五、数字格式化
实例化数字格式化对象,并且指定格式
DecimalFormat df1 = new DecimalFormat("0.0");
DecimalFormat df2 = new DecimalFormat("#.#");
DecimalFormat df3 = new DecimalFormat("000.000");
DecimalFormat df4 = new DecimalFormat("###.###");
六、java大数字运算
BigDecimal bd = new BigDecimal(3.14159263578461259445);
bd = bd.add(new BigDecimal(3.14159263578461259445));
System.out.println(bd);
七、内置类和包装类
1、装箱与拆箱
拆箱:将包装类转为基本数据类型
装箱:将基本数据类型转为包装类
1) 实现 int 和 Integer 的相互转换
可以通过 Integer 类的构造方法将 int 装箱,通过 Integer 类的 intValue 方法将 Integer 拆箱。
2) 将字符串转换为数值类型
在 Integer 和 Float 类中分别提供了以下两种方法:
① Integer 类(String 转 int 型)
int parseInt(String s);
s 为要转换的字符串。
② Float 类(String 转 float 型)
float parseFloat(String s)
注意:使用以上两种方法时,字符串中的数据必须由数字组成,否则转换时会出现程序错误。
3) 将整数转换为字符串
Integer 类有一个静态的 toString() 方法,可以将整数转换为字符串。
八、Object类
Object 是 Java 类库中的一个特殊类,也是所有类的父类。也就是说,Java 允许把任何类型的对象赋给 Object 类型的变量。当一个类被定义后,如果没有指定继承的父类,那么默认父类就是 Object 类。
提示:因为 Object 类可以接收任意的引用数据类型,所以在很多的类库设计上都采用 Object 作为方法的参数,这样操作起来会比较方便。
九、System类
System 类有 3 个静态成员变量,分别是 PrintStream out、InputStream in 和 PrintStream err。
1)PrintStream out
标准输出流。此流已打开并准备接收输出数据。通常,此流对应于显示器输出或者由主机环境或用户指定的另一个输出目标。例如,编写一行输出数据的典型方式是:System.out.println(data);
其中,println 方法是属于流类 PrintStream 的方法,而不是 System 中的方法。
2)InputStream in
标准输入流。此流已打开并准备提供输入数据。通常,此流对应于键盘输入或者由主机环境或用户指定的另一个输入源。
4)gc() 方法
该方法的作用是请求系统进行垃圾回收,完成内存中的垃圾清除。至于系统是否立刻回收,取决于系统中垃圾回收算法的实现以及系统执行时的情况。
5)getProperty() 方法
该方法的作用是获得系统中属性名为 key 的属性对应的值,
3)PrintStream err
标准的错误输出流。其语法与 System.out 类似,不需要提供参数就可输出错误信息。也可以用来输出用户指定的其他信息,包括变量的值。十、JDK自带记录日志类日志用来记录程序的运行轨迹,方便查找关键信息,也方便快速定位解决问题。下面介绍 Java 自带的日志工具类 java.util.logging 的使用。 Logger.getGlobal().info("打印日志信息");
int num = 32;
Logger.getGlobal().info("定义了int类型的num变量,值为:" + num);
Logger.getGlobal().log(Level.WARNING, "这是警告信息");
Logger.getGlobal().severe("这是严重的情况");十一、HashSet
HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时就是使用这个实现类。HashSet 是按照 Hash 算法来存储集合中的元素。因此具有很好的存取和查找性能。
HashSet 具有以下特点:
1、不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化。
2、HashSet 不是同步的,如果多个线程同时访问或修改一个 HashSet,则必须通过代码来保证其同步。
3、集合元素值可以是 null。
注意:我们说的set集合无序指的是存放元素的顺序与取元素的顺序不一致
十二、 collection接口
从集合中删除一个指定元素,当集合中包含了一个或多个元素 o 时,该方法只删除第一个符合条件的元素,该方法将返回 true。
1、利用forEach语法遍历集合元素
Java 8 为 Iterator 引入了一个 forEachRemaining(Consumer action) 默认方法,
该方法所需的 Consumer 参数同样也是函数式接口。当程序调用 Iterator 的
forEachRemaining(Consumer action) 遍历集合元素时,程序会依次将集合元素传给
Consumer 的 accept(T t) 方法(该接口中唯一的抽象方法)。
十三、 Collections 类
Collections 类是 Java 提供的一个操作 Set、List 和 Map 等集合的工具类。
Collections 类提供了许多操作集合的静态方法,借助这些静态方法可以实现集合元素的排序、
查找替换和复制等操作。
十四、try catch语句 (异常)
1、try catch语句,捕获异常并且处理异常
语法:
try{
代码块(可能出现错误的代码)
} catch(异常的类型){
处理异常的逻辑代码块
} catch () {
}.....
2、try catch finally语句
语法:
try{
可能出现异常的代码块
}catch(异常的类型){
处理异常的代码
}catch (异常的类型) {
处理异常的代码
}......{
}finally{
代码块(不管异常处理结果如何,最终都会走该语句块)
注意:该语句块是在方法结束之前调用的(return语句之前执行)
}
3、throws
当一个方法产生一个它不处理的异常时,那么就需要在该方法的头部声明这个异常,
以便将该异常传递到方法的外部进行处理。使用 throws 声明的方法表示此方法不处理异常
与 throws 不同的是,throw 语句用来直接拋出一个异常,后接一个可拋出的异常类对象
语法:
throw new 异常类型(异常信息声明)
4、如果 Java 提供的内置异常类型不能满足程序设计的需求,这时我们可以自己设计 Java 类库或框架,
其中包括异常类型。实现自定义异常类需要继承 Exception 类或其子类,如果自定义运行时异常类
需继承 RuntimeException 类或其子类。
十五、Map
Map 集合最典型的用法就是成对地添加、删除 key-value 对,接下来即可判断该
Map 中是否包含指定 key,也可以通过 Map 提供的 keySet() 方法获取所有 key
组成的集合,进而遍历 Map 中所有的 key-value 对。
map.remove("python", "new Date()");
// 这是 Java8 新增的方法,删
// 除指定 key、value 所对应的 key-value 对。如果从该 Map 中成功地删除
// 该 key-value 对,该方法返回 true,否则返回 false。
十六、List类
1、ArrayList 类实现了可变数组的大小,存储在内的数据称为元素。
它还提供了快速基于索引访问元素的方式,对尾部成员的增加和删除支持较好。
使用 ArrayList 创建的集合,允许对集合中的元素进行快速的随机访问,
不过,向 ArrayList 中插入与删除元素的速度相对较慢。
2、 LinkedList 类采用链表结构保存对象,这种结构的优点是便于向集合中插入或者删除元素。
需要频繁向集合中插入和删除元素时,使用 LinkedList 类比 ArrayList 类效果高,
但是 LinkedList 类随机访问元素的速度则相对较慢。这里的随机访问是指检索集合中特
定索引位置的元素。