一、邂逅 Java
- 想使用 Java 进行编程,就必须安装 JDK。
- JDK:开发环境。(做 Java 代码开发就必须用它。他能将我们写好的 Java 代码进行处理)。
- JRE:运行时环境。(写过的 Java 代码想运行起来,就必须有 JRE)。
- JVM:Java 虚拟机。(Java 核心。他可以将我们书写后的 Java 代码进行编译,编译成各个操作系统能看到的语言。并执行)。
- JDK --> JRE --> JVM
- Java 特点:跨平台(操作系统)。
二、Java 中的常用软件
- IDEA:功能特别强大,而且插件也很完善。 收费。
- Eclipse:曾经非常火,现在也还行。功能相对 IDEA 会差一些。现在依然很多企业再用。 免费
- MyEclipse:曾经非常火。现在几乎很少有人使用。 收费。
- STS:其实可以理解为就是 Eclipse。只不过他是 Spring 公司出品的。有个别针对 Spring 的支持比较完善。
三、Java 注释
- 注释是 Java 语言中非常重要的一个环节。
- 功能:被注释的内容,将不会被代码所执行。起到说明的作用。
arduino
// 单行注释 一次注释一行。 ctrl+/
/*开头 多行注释 结尾* 一次注释多行
/** 文本注释 结尾* 一般用于一个例或接口的说明。但是很多公司要求在接口的方法使用文档注释说明该方法的作用。
四、Java 代码书写的规则与规范
- Java 代码是高级语言、强类型语言。
- Java 代码严格区分大小写。(规则)。
- Java 中所使用的符号都必须是英文模式的符号。(规则)。
- Java 代码需要结束符号。当一段语句结束后必须使用 ; 结尾。(规则)。
- Java 所有命名不能使用关键字。(规则)。
- 写代码要有层级关系。一般我们以一队 {} 为层级。所有层级之间使用 table 缩进。 shift + table 可以回缩。
五、Java 中常用术语
- 包(package):我们可以理解为磁盘中的文件夹。用于区分不同模块的类。
- 类(Class):写程序就是在写类。我们代码都是写在类中的。他代表一类事物,是一种抽象的。
- 对象(Object):基于类创建的每一个对象。他是现实生活中存在的一个个个体。(写程序在写类,运行程序在运行对象)。
- 接口(Interface):比类更抽象。他也是一类事物的同城。与类相似,但不同。(他只定义规范),他不能创建对象。
- 变量(variable):在内存中开辟一块空间,用来存储我们程序运行时所需要的数据。在运行期间,该值是可能改变的。不到程序运行结束,我们永远不知道该变量最终结果。
- 常量(了解):定义初期就要赋值。一旦定义该值无法改变。使用 final 修饰。
- 方法(method):一段通过名字就能执行具体功能的代码。
六、Java 中命名规则与规范
- 规则及规范:
-
-
命名时可以使用英文、数字、$、_。但是不能以数字开头。不允许有特殊符号。不能使用关键字。可以使用但不建议使用中文字符、命名不宜过长。
-
包命名:所有字母都小写。(一般是公司域名的反写) www.baidu.com com.baidu
-
类/接口:首字母大写,多个单词组成时每个单词首字母都大写(驼峰写法)。
-
变量:首字母小写,多个单词组成时每个单词首字母都大写(驼峰写法)。
-
常量:所有字母大写、多个单词组成使用 _ 分割。
-
七、Java 中的数据类型。
-
基本数据类型
-
- 四类八种
-
- 数值型
-
-
整数型
-
byte(几乎不用):字节型, -128~127 256
-
short(几乎不用):短整型, 65536
-
int:整形(默认值) ,用的非常多。 2^64 +-19E
-
long:长整型, int 有可能装不下就用它。会持续增长的也用它。 结尾需要添加一个 l 或 L 191L
-
浮点型(小数)
-
float:单精度,很少用。 结尾需要添加一个 f 或 F 15.4F
-
double:双精度,默认值。
-
-
-
- 字符型
-
- char:一个字符。可以是一个中文、一个英文、一个数字。 必须使用一对单引号包裹。 '中'、'a'。
-
-
-
- 布尔类型
-
- boolean: true false
-
-
引用数据类型
-
- 无数种,除了基本数据类型都是引用数据类型
-
- 我们只要自己创建了一个类,就等于声明了一种数据类型。
- JDK 中为我们提供了一些常用的引用数据类型。
-
-
String:字符串 --> 一串字符。用的最多最多最多的。 必须 "" 一对双引号包裹。 "你好中国"。在字符串内的数据都是原样输出。
-
Date:日期类。
-
Class:类
-
Object:对象
-
Array:数组
-
List/Set/Map:集合
-
Calendar:日历类。(日期的运算)。
-
BigDecimal:精确型小数。一般用于 Money。
-
八大基本数据类型对应的包装类
-
byte --> Byte
-
short --> Short
-
int --> Integer
-
long --> Long
-
float --> Float
-
double --> Double
-
char --> Character
-
boolean --> Boolean
-
-
- 行业内,又自成一种规范(这种规范并不是 Java 官方认可的)。简单类型
-
- 他并不是官方推出的。是业内人士(广大程序员们),默认自主承认的一种数据类型。他会把我们 基本数据类型 + 常用引用数据类型放到一起的称呼。 8 大把基本数据类型 + 包装类 + String + BigDecimal 等等...
八、Java 中的数据类型转换(了解)
-
基本数据类型转换
-
- 在 Java 中 boolean 类型不参与任何转换。
- 隐士转换(自动转换)(常用)
-
- 小转大
-
-
byte、short、char 三种不能相互转换。
-
byte、short、char --> int --> long --> float --> double
-
-
- 显示转换(强制转换)(慎用)
-
- 大转小
-
-
需要强制使用 () 转换 例如 byte b = (byte)32Z
-
一定要慎用,因为可能会丢失精度。
-
-
引用数据类型转换(常用)
-
- 只要能包含的情况下。我们可以使用 () 为前缀。使用具体数据类型进行转换 (String)"abc"。
九、Java 中的变量。
-
在内存中开辟一块空间,用来存储我们程序运行时所需要的数据。在运行期间,该值是可能改变的。不到程序运行结束,我们永远不知道该变量最终结果。
-
变量如何使用
-
- 变量的声明
数据类型 引用名;
int i;
-
- 变量的初始化
引用名 = 值;
i = 10;
-
- 建议写法 声明 + 初始化
数据类型 引用名 = 值;
int i = 10;
-
- 在同一块作用域内,变量的名字是禁止重复的(花括号)。
- Java 基础中。若程序想运行就必须有一个主方法。主方法就是程序运行的入口。 简写 main psvm
public static void main(String[] args){ // 这里面就是需要执行的代码。 }
-
- 输出语句,简写 sout
System.out.println(「需要输出的语句」);
-
- Demo
package day01; /** * 数据类型及变量 * public class _01_Variable { // 主方法,程序的入口。 public static void main(String[] args) { // 使用变量定义一些数据类型 byte b = 10; short s = 20; int i = 30; long l = 40L; float f = 12.3F; double d = 20.2; char C = 『a』; boolean bl = true; String str = 「今天真开心,终于可以写代码了」; // System.out.println(需要输出的语句); 简写 sout System.out.println(「变量 b」 + b); System.out.println(str); final int USER_ID = 123; } }
十、Java 中的常量(了解)
- 声明后不能直接使用,若想使用必须初始化。(创建后必须赋值)
- 修饰符 final
- 例如 final int USER_ID = 22;
十一、运算符
- 赋值运算符
- = 赋值, Java 是从右向左赋值。需要注意数据类型。
- 算数运算符
-
-
-
- / ++ -- %
-
-
-
- 号:
-
-
在正常数学运算时,做加法运算。
-
存在字符串时,做连接符号。
-
-
-
/ Java 中除法不存在小数。0 不能做除数。
-
++ 自增 1
-
-- 自减 1
-
自增自减:++在前 先加后用。 ++在后先用后加。
-
% 取余。 取除法的余数。
-
- 条件运算符
-
条件运算符得到的结果一定是一个 boolean 值。也就意味着结果只有真和假
-
String 类型比较使用 equals() 方法.
-
= < <= == !=
- 逻辑运算符
-
作用:就是用来链接条件运算符的。
-
很多时候我们一个条件不够用的时候。需要多个条件。那么就需要使用逻辑运算符来链接多个比较运算符。
-
&&:逻辑与,并且的意识。多个条件都为真,结果才是真。
-
||:逻辑或,或者的意识。多个条件中任意一个为真,结果才是真。
-
!:取反,真亦假,假亦真。
-
作业:自行了解 短路机制。
- DEMO
ini
package day01;
/**
* 运算符
* /
public class _02_Operator {
public static void main(String[] args) {
// +
System.out.println(1 + 2); // 正常数学运算
System.out.println(「嘿嘿」 + 「1」 + 「2」); // 看到双引号就是字符串。做连接符
// 除法没有小数,且没有四舍五入。
System.out.println(5/2);
// System.out.println(1/0);
System.out.println(「----------- 自增自减 --------------」);
int i = 3;
System.out.println(i++);
System.out.println(i);
System.out.println(「--------- 取余 -----------」);
System.out.println(5%2);
System.out.println(「-------- 条件运算符 --------」);
System.out.println(5 > 3); // true
System.out.println(3 != 4); // true
System.out.println(「---------- String 字符串比较 ------------」);
String str1 = 「zhangsan」;
String str2 = 「lisi」;
System.out.println(str1.equals(str2)); // false
System.out.println(「abc」.equals(「abc」)); // true
System.out.println(「---------- 逻辑运算符 ---------」);
int a = 18;
System.out.println(a > 10 && a <= 18); //true
System.out.println(a > 15 || a < 17); // true
}
}
十二、分支语句
- 分支语句会影响程序的走向。正常程序是从上至下依次执行。
- 判断
- if 如果...
if(条件表达式){ // 若条件表达式的值为 true,则执行该语句块内的代码。 } // if 内的语句是由可能执行到,也可能执行不到。 package day01; /** * if 判断 * / public class _03_if { public static void main(String[] args) { // 设置一个 age 年龄。若 age >= 18 则可以包宿。 int age = 19; if(age >= 18){ System.out.println(「wa o ~ 终于可以包宿了~」); } System.out.println(「.... 后续代码执行」); } }
- if...else 如果... 否则...
csharp
if(条件表达式){
// 若条件表达式的值为 true,则执行该语句块内的代码。
} else {
// 若不满足条件则执行该语句块内的代码。
}
// if..else 无论如何, if || else 一定会执行到里面某一个语句块。
package day01;
/**
* if...else 判断
*/
public class _04_if_else {
public static void main(String[] args) {
// 设置一个 age 年龄。若 age >= 18 则可以包宿。
int age = 17;
if(age >= 18){
System.out.println(「wa o ~ 终于可以包宿了~」);
} else {
System.out.println(「小屁孩,回家睡觉吧~」);
}
System.out.println(「.... 后续代码执行」);
}
}
-
if...else if..else 如果... 否则 如果... 否则...
-
- 若满足某一个条件后,当前判断立即结束。后续代码继续执行。
scss
if(条件表达式){
// 若条件表达式的值为 true,则执行该语句块内的代码。
} else if(条件表达式) {
// 若条件表达式的值为 true,则执行该语句块内的代码。
} else if(条件表达式) {
// 若条件表达式的值为 true,则执行该语句块内的代码。
}
...
else {
// 若都不满足条件则执行该语句块内的代码。
}
package day01;
/**
* if...else if 判断
*/
public class _05_if_else_if {
public static void main(String[] args) {
double money = 500;
// 请女朋友吃饭。
if(money >= 1000){
System.out.println(「走,吃海鲜去」);
} else if(money >= 600){
System.out.println(「走,吃西餐吧」);
} else if(money >= 400){
System.out.println(「走,吃火锅吧」);
} else if(money >= 200){
System.out.println(「吃,吃烤肉吧」);
} else {
System.out.println(「回家吃面条吧!!」);
}
}
}
- 循环
- for:已知次数的循环
for(循环变量初始值;循环条件;步进语句){ 循环体;(循环需要执行的代码) } package day01; /** * for 循环 */ public class _06_for { public static void main(String[] args) { // 循环变量初始值:一个初始变量,我们需要开始的起始数字。 // 循环条件:条件表达式。当条件表达式的结果为 true 则执行循环体。false 则停止循环。 // 步进语句:控制循环变量初始值的增减,目的是停止循环。 // 计算从 1 ~ 100 的和; int sum = 0; // 累加结果 for(int i = 1;i <= 100;i++){ sum = sum + i; } System.out.println(sum); } }
-
- while:未知次数的循环
while(循环条件){ 循环体; } package day01; /** * while 循环 */ public class _07_while { public static void main(String[] args) { // 计算从 1 ~ 100 的和; int sum = 0; // 累加结果 int i = 1; while(true){ if(i > 100){ break; // 停止循环 } sum = sum + i; i++; } System.out.println(sum); } }
-
- do..while:无论是否成功都先执行一次
do{ // 循环体 }while(循环条件); package day01; /** * do...while 循环 */ public class _08_do_while { public static void main(String[] args) { // 计算从 1 ~ 100 的和; int sum = 0; // 累加结果 int i = 1; do{ sum += i; i++; }while(i <= 100); System.out.println(sum); } }
十三、Java 中的数组
-
定义:数组就是相同数据类型 的集合。在内存中开辟一块连续的内存空间 用来存储我们所需要的数据。数组的长度一经定义无法改变
-
特点:
-
-
存储相同数据类型
-
数组是有序的。(存储数据的顺序)。
-
长度无法改变。
-
-
语法规则:
ini
// 数组的定义
// 数据类型[] 引用名;
// 后续再初始化
// 数据类型[] 引用名 = new 数据类型[3];
// 数据类型[] 引用名 = new 数据类型[] {值 1,值 2,值 3,值 4}
// 我们都使用简易方式创建书写
// 数据类型[] 引用名 = {值 1,值 2,...}
- 对数组的顺序表示我们称之为索引(下标)。索引是从 0 开始的。
csharp
package day01;
/**
* 数组
*/
public class _09_Array {
public static void main(String[] args) {
// int[] arr1 = new int[3]; // 3 长度的数组
// int[] arr2 = new int[]{1,2,3,4};
// 数组声明并初始化
int[] arr = {1,2,6,3,2};
// 数组是有序的。对顺序的表示我们称之为 索引(下标)。索引从 0 开始
System.out.println(「arr 数组中第二个元素为:」 + arr[1]);
// 若想一次性将数组中的所有元素都取出。
// 数组的最大索引等于 数组的长度 - 1。
// 数组中存在一个属性。 .length 他就是数组的长度
System.out.println(「该数组长度为:」 + arr.length);
System.out.println(「=====================」);
// 数组的遍历
// i 就是我们所谓的「索引」。
for(int i = 0;i < arr.length;i++){
System.out.println(arr[i]);
}
System.out.println(「♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥」);
// 对于数组 还有后面学习的集合。我们有一种增强 for 循环的方式遍历
// for(数据类型 引用名 : 数组名){
// 通过引用名获取到每一个元素
// }
for(int temp : arr){
System.out.println(temp);
}
}
}
十四、Java 中的方法(重点)。
-
定义:其实他就是一段有名字的代码。该段代码可以完成指定的功能。
-
为什么要用方法?
-
-
代码的复用:我们可以将一段完整的功能封装为一个方法。多处使用到该功能时直接调用该方法即可。
-
易于维护:我们针对于某一种功能封装后,多处都可以使用。当我们将方法内的内容改变后。多处代码也随之更改。这样就可以实现一处修改。多处实现。
-
单一原则:一个方法只完成一件事情。
-
-
方法的组成
-
-
方法的首部声明
-
方法体
-
-
语法
scss
// 带有 [] 包裹的,是可选择性写或不写的。
[权限修饰符] [修饰符] 返回值类型 方法名([形参 1,形参 2,...]) // 方法的首部生命
{
// 方法体
// 需要执行的功能
[return xxx;]
}
-
权限修饰符:public 公共的,当前项目中谁都可以访问 。在什么位置能够访问到我们的当前的方法。
-
修饰符:
-
-
static:静态的。可以通过类名.方法名的方式调用。若是本类方法。则可以直接在静态方法中直接调用,不需要类名。
-
abstract:抽象的。(接口部分讲解)
-
final:最终的。(了解。继承部分说一下)
-
-
返回值类型:我们执行方法后,需要该方法为我们返回什么类型的数据。若需要则需要定义返回值类型。若不需要返回任何数据也必须使用 void 占位。
-
方法名:该方法的引用名,我们可以通过该引用名找到该方法。
-
形参列表:当我们调用方法时,是否需要传递某些数据。
-
-
形参列表本质上可以理解为是我们方法中一些变量。只不过这个变量只做了声明。未初始化。(只创建了,没赋值)。当该方法的调用者调用时,将具体的值传入。
-
方法的形参可以是 Java 中的任意类型。可以是 0 ~ 任意个。但是不建议过多。一般很少有超过 5 个的。
-
-
方法体:该方法具体需要实现的功能。
-
return 语句:
-
-
有返回值类型时:必须使用 return 语句。我们需要在 return 语句后返回一个数据,该数据的数据类型必须与返回值类型相容。(一般我们的返回值的数据类型都会与方法的返回值类型一致)。
-
若没有返回值类型时:可以有也可以没有。若写 return 则不能返回任何数据。 return 只代表方法的结束。
-
return 是方法的最后一条可执行语句。
-
-
方法需要定义在类中。与主方法平齐。方法不能嵌套。
csharp
package day01;
public class _10_method {
// 主方法
public static void main(String[] args) {
}
// 无参数无返回值的方法
public static void show(){
System.out.println(「我是无参数我返回值的方法」);
}
// 有参数无返回值的方法
public static void addTwo(int a,int b){
System.out.println(「两数之和为:」 + (a + b));
}
// 无参数有返回值的方法
public static String showTwo(){
return 「爱你」;
}
// 有参数有返回值的方法
public static int sub(int a,int b){
return a - b;
}
// 没有返回值的 return 语句
public static void add(int a,int b){
if(a > b){
System.out.println(「哈哈」);
return;
}
System.out.println(「a < b 我输出了」);
}
}
-
方法的调用。
-
-
我们暂时先都说静态方法。
-
若是本类中。静态方法可以直接调用静态方法。不需要类名。
-
其他类中若调用静态方法。(前提是访问权限修饰符能够访问到)。需要类名.方法名() 方式调用。
-
-
方法的重载
-
- 在同一个类中,方法名相同,参数列表不同(长度,类型,不同类型的顺序不同)
package day01; /** * 方法的重载 */ public class _11_Overload { public void add(int a,String b){ }; public void add(String a,int b){ } }
- 方法不能主动执行。它必须被调用才能执行。
十五、Java 面向对象思想(重点)。
- 类
-
现实生活中存在的一类事物。存在着某些共性(共性抽取)。泛指一类事物。他是抽象的,是现实生活中不存在的。
-
类是对象的模板。
-
-
静态属性:属性。
-
动态行为:方法。
-
-
- 写程序在写类。运行程序运行的是对象。
- 对象
-
对于一类事物中的具体存在的个体。我们称之为对象。他是显示生活中真实存在的个体。
-
对象是类的实例。
-
每个对象都应该存在类的属性及方法。但是每个对象都有自己的属性值。
-
创建对象就需要构造方法。
- 构造方法
- 构造方法也是方法,只不过它是一种特殊的方法。
- 要求方法名与类名相同,没有返回值,也不需要 void 占位。构造方法可以被重载。
- 构造方法的作用:
-
创建对象(最大的作用)。
-
还可以在创建对象时为其赋值。
-
- 使用构造方法创建对象需要使用 new 关键字。
- 只要我们写了一个类,就存在构造方法。若我们没有明确的写出构造方法。那么系统会送我们一个无参数无方法体的空构造方法。若我们明确的写出了其他形式(带参数)的构造方法。那么系统将不再赠送。
- 无参及有参构造方法的书写
package day02._01_obj; public class Student { public String name; public Integer age; // 我们没有明确写出构造方法,系统会送我们一个无参数五方法体的构造方法。若写了则不送了,需要则自己写。 // 一般我们只要写了有参构造方法,都会手动添加一个无参数构造方法。(后期框架会调用) public Student() { } // 若我们自己书写了携带参数的构造方法,那么系统将不再赠送。 public Student(String name,Integer age){ // Java 中存在就近原则。谁离着进, name 就指向谁。 // 若方法中的形参名与类中的属性名一致,我们可以使用 this 关键字。 // this 指向本类。 this.name = name; this.age = age; } public void eat(){ System.out.println(「中午订一份得了」); } @Override public String toString() { return 「Student{」 + 「name=『」 + name + 』\『』 + 「, age=」 + age + 『}』; } }
-
- 创建对象
package day02._01_obj; public class ObjTest { public static void main(String[] args) { // 创建对象 Student stu = new Student(); // Student: 数据类型 // stu:引用名 // new: 内存分配符。(只要看到 new,就是在内存中开辟空间) // Student():构造方法,创建对象。 // 调用成员属性及方法(非 static 修饰的)。我们使用 对象名.属性/方法 名调用。 stu.name = 「张三」; stu.age = 35; stu.eat(); System.out.println(stu); Student stu2 = new Student(「李四」,12); System.out.println(stu2); } }
- 封装
- 将内部细节隐藏起来。对外只暴露统一的接口。
- 好处:安全、便捷、高效、解耦。
- 访问权限修饰符:
| 四种访问权限修饰符 | 不同包下的不同类 | 相同包下的不同类 | 本类 | | --------------------------------------- | -------------------------------------------------- | ---------------------------------- | ---------------------------------- | | public 公共的 | √ | √ | √ | | protected 受保护的(了解) 父子类相互使用 | X(继承下可以使用) | √ | √ | | 默认的(什么都不写) | X | √ | √ | | private 私有的 | X | X | √ |
-
-
我们最常用的 (public private)
-
private 的权限最小,最适合做封装。也是我们用的最多的用于封装的。但是不代表只有 private 能做封装。其他任何访问权限修饰符都可以做封装。只不过 private 用的最多。
-
我们利用封装思想。可以完成标准 JavaBean。 (将来这种 JavaBean 他可以用于接受 Web 用户传递的请求时候携带的参数。也可以与数据库做数据交互使用)。
-
标准 JavaBean
-
-
所有属性私有化。
-
为每一个属性都提供一对共用 Getter/Setter 方法。
-
提供有参无参构造方法(可选)。
-
若需要展示当前对象数据(调试)。提供 toString 方法。
-
-
package day02._02_createObj; /** * 封装 * 封装标准 JavaBean */ public class Student { // 所有属性私有化 private Long id; private String name; private Integer age; public Student() { } public Student(Long id, String name, Integer age) { this.id = id; this.name = name; this.age = age; } // Set 方法可以对非法数据进行验证。 public void setName(String name){ if(name.equals(「二狗」)){ this.name = 「帅哥」; return; } this.name = name; } public String getName(){ return this.name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return 「Student{」 + 「id=」 + id + 「, name=『」 + name + 』\『』 + 「, age=」 + age + 『}』; } }
-
- 测试类
package day02._02_createObj; public class StudentTest { public static void main(String[] args) { Student stu = new Student(); // 设置属性值 stu.setName(「二狗」); // 获取属性值 System.out.println(stu.getName()); } }
- 继承
-
继承在 Java 是广泛存在的,所以在 Java 中我们将继承关系又称之为 "泛化关系"。是类就存在继承关系。若一个类没有明确写出继承关系。那么这些类都继承所有类的父类 Object 类。
-
-
父类(被继承类)、基类
-
子类(继承类)、派生类
-
-
- 继承的关键字 extends
- 继承不要乱继承。继承必须存在关系才可以继承 is - a。是一种关系。
- 继承的作用:子类可以继承父类中所有非私有(private)修饰的属性和方法。
- 我们在使用时,一般会将父类中定义基础的属性及方法。子类继承后就可以拥有父类中定义的基础属性和方法。同时可以扩展自己的属性及方法。所以子类就是对父类的扩展。简化代码。
- Java 中是单继承。一个子类只能存在一个直接父类。一个父类可以存在若干个子类。
- Java 中是可以存在继承链的,但不宜过多。
- 继承中,若存在同名属性,则就近原则(本类,子类中的属性值)。
- 方法的重写:发生在继承/实现时候。子类重写了父类的方法。方法名相同,参数列表和返回值类型都相同。
- 我们可以使用 @Override 注解来测试该方法是否为重写方法。若该注解报错则说明不是重写方法。一般重写的方法我们都会在该方法上面贴上 @Override 来标识。
- 父类 Animal
package day02._03_extends; /** * 动物类 * 父类 */ public class Animal { public String name = 「小猪」; public Integer age; public void eat(){ System.out.println(「动物吃饭」); } }
-
- 子类 Dog
package day02._03_extends; /** * 子类 * 继承 Animal 动物类 */ public class Dog extends Animal{ public String name = 「gogo」; @Override public void eat() { System.out.println(「小狗吃骨头」); } }
-
- 子类 Cat
package day02._03_extends; /** * 子类 * 继承 Animal 动物类 */ public class Cat extends Animal{ @Override public void eat() { System.out.println(「小猫吃鱼」); } }
-
- 子类 Tiger
package day02._03_extends; /** * 子类 老虎 * 继承 Animal */ public class Tiger extends Animal{ @Override public void eat(){ System.out.println(「小老虎吃肉肉」); } }
-
- 测试类
package day02._03_extends; public class ExtendsTest { public static void main(String[] args) { Dog dog = new Dog(); dog.age = 2; System.out.println(dog); System.out.println(「===============」); dog.eat(); Cat cat = new Cat(); cat.age = 2; System.out.println(cat); System.out.println(「===============」); cat.eat(); System.out.println(「♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥」); // 饲养员给动物喂食 Person person = new Person(); Cat C = new Cat(); Dog d = new Dog(); Tiger t = new Tiger(); person.feed(t); } }
- 多态
-
类多种形态的表现
-
实现多态的条件
-
-
继承(实现)。
-
方法的重写。
-
(类 --> 对象 --> 方法)动态绑定。
-
-
- 向上转型(李氏代换)。 --> 自动转换
- 父类的引用 --> 指向子类的对象。
- Demo
- 父类 Animal
package day02._04_polymorphism; /** * 动物类 * 父类 */ public class Animal { public String name = 「小猪」; public Integer age; public void eat(){ System.out.println(「动物吃饭」); } }
-
- 饲养员类
package day02._04_polymorphism; /** * 饲养员类 * * 饲养员要给小动物喂食 */ public class Person { // Animal an = new Tiger(); public void feed(Animal an){ an.eat(); } }
-
- 测试类
package day02._04_polymorphism; public class ExtendsTest { public static void main(String[] args) { // 饲养员给动物喂食 Person person = new Person(); // 创建父类类型 Animal // Animal an = new Animal(); // 执行结果为 动物吃饭 // 父类的引用 --> 指向子类的对象。 Animal d = new Dog(); Animal C = new Cat(); Animal t = new Tiger(); person.feed(t); } }
-
-
父类的引用指向子类的对象。这种方式创建出来的对象是谁?
-
-
既不属于父类,也不属于子类。
-
该对象 - 编译期(代码未运行时): 用的属性及方法看 = 左边。 - 运行期(代码跑起来后): 用的属性及方法看 = 右边。
-
-
-
- 若想使用子类特有的属性及方法 必须向下转型
- 向下转型必须是向上转型得到的对象才可以
- 不要随意使用。小心类型异常。
package day02._04_polymorphism; public class ExtendsTest { public static void main(String[] args) { // 饲养员给动物喂食 Person person = new Person(); //Cat C = new Cat(); //Dog d = new Dog(); //Tiger t = new Tiger(); // 创建父类类型 Animal // Animal an = new Animal(); // 执行结果为 动物吃饭 // 父类的引用 --> 指向子类的对象。 Animal d = new Dog(); Animal C = new Cat(); Animal t = new Tiger(); person.feed(t); // 向上转型得到的对象 System.out.println(d.name); // 父类=小猪 子类=gogo 结果为小猪 父类属性值 d.eat(); // 父类=动物吃饭 子类=吃骨头 结果为 小狗吃骨头 // 若想使用子类特有的属性及方法 必须向下转型 // 向下转型必须是向上转型得到的对象才可以 Dog dog = (Dog) d; System.out.println(dog.color); dog.run(); } }
十六、接口(重点)
-
接口也代表了一类事物。
-
接口他是抽象的,他比类更抽象。他更多的是提供了一组规范。提供模板。
-
接口关键字 Interface。接口不提供实现。他不能创建对象。
-
- JDK8 之前:
-
-
接口中只能存在静态常量。默默人修饰符 public static final。
-
接口中 方法都是抽象方法。由 abstract 修饰。抽象方法只有方法的首部声明,没有方法体。默认修饰符 public abstract 。他是提出一组规范让他去使用。
-
-
- JDK8 之后:
-
- 出现了静态方法、默认方法。 JDK9 之后出现了私有方法。(存在方法体的)。
-
接口不是类,不能创建对象。所以他的一切方法都需要交给别人去处理。(实现类)。
-
接口就是用来定义规范的。定义规范后由类去实现接口。并实现接口中所有抽象方法。这些实现接口功能的类我们称之为实现类。
-
类去实现接口的关键字 Implements。
-
-
提供规范。
-
解决 Java 单继承问题。
-
-
一个类只能继承一个直接父类。但是可以实现若干个接口。
-
很多时候,我们都是用 接口 --> 实现类方式书写代码。这样代码的可扩展性更高。
-
接口 A DEMO
csharp
package day02._05_Interface;
public interface A {
void eat();
}
- 接口 B DEMO
csharp
package day02._05_Interface;
public interface B {
void run();
void show();
}
- 实现类 DEMO
less
package day02._05_Interface;
/**
* 接口实现类
* 一个类可以继承一个直接父类,同时实现多个接口。使用 , 分割。
*/
public class InterfaceImpl extends Animal implements A,B{
@Override
public void eat() {
System.out.println(「他要吃 XXX」);
}
@Override
public void run() {
}
@Override
public void show() {
}
}
- 测试类
java
package day02._05_Interface;
public class InterfaceTest {
public static void main(String[] args) {
// 创建 A 接口对象
// 接口 实现类的方式创建
A a = new InterfaceImpl();
B b = new InterfaceImpl();
a.eat();
b.run();
b.show();
}
}
十七、异常处理
-
当我们书写代码。运行程序时都可能出现各种各样的问题。此时就与异常处理相关。
-
程序出现异常有两种情况
-
-
Error:错误,灾难性的、致命的。一般无法通过小的改动而去拯救。 相当于得了绝症。
-
Exception:异常,一般是书写代码错误或逻辑错误导致的。通常通过一些小的代码改动就能解决。 相当于得了个小感冒。
-
-
异常分类
-
- 编译期异常:编译期就是代码未运行期间的错误。
-
-
要么就是我们自己代码敲错了。
-
系统级的。这种一般我们简单处理即可。
-
-
- 运行期异常:
-
- 代码跑起来之后才会出现的异常。这种普遍就是程序员们逻辑出现问题。需要修改代码。(我们一般都处理这个运行时异常。) RuntimeException
-
我们一般都是针对运行期异常进行处理
-
异常处理有三种方式
-
-
try/catch/finally:我们自己捕获到异常并处理异常
-
-
try:语句块中是可能出现异常的代码。
-
catch:若出现了异常,那我们如何处理该异常。
-
finally:无论该代码是否出现异常都会执行。(一般用于关闭资源)
-
-
package day02._06_exception; /** * 捕获异常 * try catch finally */ public class Try_Catch { public static void main(String[] args) { // 在 try 中捕获可能出现的异常 // 在 catch 中处理出现的异常。 try{ System.out.println(1/0); System.out.println(「若代码没出现异常执行该代码...」); } catch (RuntimeException e){ // 需要捕获的异常类型。 e.printStackTrace(); // 在控制台中显示异常。 // 若出现了该类型的异常则执行该语句块 System.out.println(「出现了异常,我们去处理该异常」); } finally { // 无论是否产生异常,都执行该语句块 System.out.println(「关闭资源」); } } }
-
-
throws:抛出异常类型。
-
-
在方法上面声明。抛出的是异常类型。
-
所谓的抛出异常,其实就是自己不处理该异常。向上抛出。谁调用我谁就来处理该异常。若谁都不处理这个异常。那么最终交给 Java 虚拟机来处理。 Java 虚拟机会直接采取中断处理(直接停止我们程序执行)。
-
一般一些编译期异常用的较多。例如文件是否能够找到。磁盘是否存在这些。
-
-
package day02._06_exception; import Java.io.FileNotFoundException; /** * 异常抛出 */ public class ThrowsTest { public static void main(String[] args) { ThrowsTest t = new ThrowsTest(); try { t.showTwo(); } catch (FileNotFoundException e) { throw new RuntimeException(e); } } public void showTwo() throws FileNotFoundException{ System.out.println(「被调用了」); show(); } public void show() throws FileNotFoundException { System.out.println(「产生异常的代码.」); System.out.println(1/0); System.out.println(「异常抛出」); } }
-
-
throw:在代码中抛出指定异常。
-
- 一般我们可以自定义异常抛出的信息。很多时候我们在 WEB 程序中,作为自定义指定内容输出。
-
package day02._06_exception; public class LoginTest { public static void main(String[] args) { LoginTest login = new LoginTest(); // 该方法是抛出了异常的 try { login.login(); System.out.println(「登录成功」); } catch (RuntimeException e) { System.out.println(「给用户展示错误消息:」 + e.getMessage()); } } public void login() throws RuntimeException{ // 假设用户传递了用户名 zs 密码 123 String username = 「zs1」; String password = 「123」; // 调用方法去处理登录请求 checkUserNameAndPassword(username,password); } public void checkUserNameAndPassword(String username,String password){ // 对比用户名是否正确 if(!(username.equals(「zs」) && password.equals(「123」))){ throw new RuntimeException(「账号密码有误」); } } }
十八、集合(数据结构)
-
集合概述:可以存储多个数据。集合中也可以存储多种数据类型(但是实际开发中不建议这么做)。集合中只能存储引用数据类型。
-
集合的分类:
-
-
单列集合:Collection 父接口 --> (List 接口,Set 接口)
-
双列集合:Map 父接口
-
List:(列表)
-
-
List 集合中有多个实现类。
-
我们最常用的 ArrayList。他的底层数据结构为 动态数组。本质上就是数组。只不过可以自动扩容。初始值为 10.扩容机制为 1.5 倍。
-
特点:
-
-
可以存储多种数据类型(实际开发中不建议这么做)。
-
有序的。(索引)。
-
可以存储重复数据。
-
存在扩容机制。
-
-
-
-
-
- 案例:
-
package day02._07_gather; import Java.util.ArrayList; import Java.util.List; /** * List 接口 * 实现类 ArrayList */ public class _01_ArrayList { public static void main(String[] args) { List list = new ArrayList(); // 添加数据 add() 方法。 list.add(「abc」); list.add(1); list.add(true); // 获取数据 System.out.println(list.get(0)); System.out.println(list.get(1)); System.out.println(list.get(2)); // 一次性获取多个集合中的数据 遍历 for(Object obj : list){ System.out.println(obj); } } }
-
-
但是实际开发中不建议存储多种类型。所以我们需要使用 泛型来约束集合中存储的类型。
-
泛型:
-
- 可以使用在 接口、类、方法、集合中。本次主要讲解集合中使用泛型。
- 最用:就是规定集合中存储的类型
- 使用方式 <类型>;
-
package day02._07_gather; import Java.util.ArrayList; import Java.util.List; /** * 泛型 */ public class _02_Generic { public static void main(String[] args) { List list = new ArrayList<>(); list.add(1); list.add(5); list.add(3); for (Integer i : list) { System.out.println(i); } } }
-
-
Set:(集合)
-
-
我们最常用的 Set 集合子类是 HashSet。他的底层是 hash 表 + 双链表结构 + 红黑树。
-
特点:无序且唯一。
-
案例
-
-
package day02._07_gather; import Java.util.HashSet; import Java.util.Set; /** * Set 集合 * HashSet 子类。 */ public class _03_Set { public static void main(String[] args) { Set set = new HashSet<>(); set.add(「Hello」); set.add(「Java」); set.add(「Python」); // 遍历来获取 Set 集合中的数据。 // Set 集合是无序的,所以不能使用普通 for 循环。 // 老办法使用迭代器。 // Iterator iterator = set.iterator(); // while (iterator.hasNext()) { // 是否有下一个元素 // System.out.println(iterator.next()); // 拿到下一个元素 // } // 也可以使用增强 for 循环。 for(String str : set){ System.out.println(str); } } }
-
-
Map:(映射)
-
- Key --> Value 键值对的形式存在。 使用 Key 映射 Value。
- 我们最常用的是 HashMap。 底层 哈希表。
- 特点双列集合。双列对应的就是 Key Value。
- Key 是不能重复的, Value 可以重复。Key 若重复后面的值会覆盖前面的值。
-