一、面向对象(类和对象)
1.1 万事万物皆对象
类:对对象向上抽取出像的部分、公共的部分以此形成类,类就相当于一个模板。
对象:模板下具体的产物可以理解为具体对象,对象就是一个一个具体的实例,就相当于这个模板下具体的产品。
Java中一般先定义类,再创建对象
1.2 类和对象的关系
(1)类的定义
- 给类起一个见名知意的名字,首字符大写,驼峰命名原则,
- 类的特性编写,特性即类的属性部分。
- 类的行为编写,行为即类的方法部分。
(2)类和对象的创建以及使用
类的定义
public class Person {
// 特性编写-属性-名词(只定义和业务逻辑相关的代码)
String name; // 姓名
int age; // 年龄
double height; // 身高
// 行为编写-方法-动词
// 定义一个学习的方法
public void study() {
System.out.println("study>>>>>>");
}
}
对象的创建和使用类
public class Test {
// 程序的入口
public static void main(String[] args) {
// 对Person类的对象进行创建:创建了一个Person对象,名字叫p1
Person p1 = new Person();
// 对属性进行赋值操作
p1.name = "张三";
p1.age = 18;
p1.height = 178.5;
// 读取属性
System.out.println(p1.name);
System.out.println(p1.age);
// 调用对象的方法
p1.study();
}
}
二、构造器
2.1 构造器的作用
对于一个类来说,一般有三种常见的成员:属性、方法、构造器。这三种成员都可以定义零个或多个。
构造方法也叫构造器,是一个创建对象时被自动调用的特殊方法,用于对象的初始化。Java通过new关键字来调用构造器,从而返回该类的实例。
2.2 构造器声明格式
若无参数列表,称之为无参构造器(空构造器)
若有参数列表,称之为有参构造器
2.3 构造器四要点
- 构造器的方法名必须和类名一致
- 构造器通过new关键字调用
- 构造器不能定义返回值类型,不能在构造器里使用return关键字来返回某个值。
- 如果我们没有定义构造器,则编译器会自动定义一个无参的构造方法。如果已定义则把编译器不会自动添加
2.4 构造器的重载
构造方法也是方法,只不过有特殊的作用而已。与普通方法一样,构造方法也可以重载。
2.5 创建构造器的快捷键
8Alt + Insert
2.6 代码示例
Person类
// 特性编写-属性-名词(只定义和业务逻辑相关的代码)
String name; // 姓名
int age; // 年龄
double height; // 身高
// 行为编写-方法-动词
// 定义一个学习的方法
public void study() {
System.out.println("study>>>>>>");
}
// 定义一个构造器
public Person() {
System.out.println("调用了一个空构造器");
}
// 重载一个构造器
// 构造器的参数名字:如果和属性名字重名,就会发生就近原则
// 如果重名以后,你想给属性赋值,那么就在想要表达属性的变量前加上 this. 修饰
public Person(int age, String name, double height) {
this.age = age;
this.name = name;
this.height = height;
}
Test02对象
public class Test02 {
public static void main(String[] args) {
// 创建一个Person类的对象
/* new Person()解释
Person():空的构造方法
new关键字:对方法进行调用=》构造器作用:底层会帮我们创建对象,在创建对象之后进行初始化操作
如果一个类没有显示编写构造器的话,那么系统会为这个类默认分配一个空构造器
调用构造器以后,对对象进行初始化操作,将对象的地址返回给p
尽量要保证空构造器的存在,因为某些框架底层需要空构造器,如果你没有添加就会报错
*/
/*
原始写法
Person p = new Person();
p.age = 18;
p.name = "小张";
p.height = 180.6;
Person p2 = new Person();
p2.age = 18;
p2.name = "小李";
p2.height = 160.6;
*/
// 简便写法
Person p = new Person(18,"小张",180.6);
System.out.println(p.age);
Person p2 = new Person(30, "小李",160.6);
System.out.println(p2.age);
// 如果一个类中有构造器,那么系统就不会为你分配默认的构造器
// Person p3 = new Person(); // 会报错
}
}
三、面向对象(封装)
3.1 封装的思想
我们程序设计追求“高内聚,低耦合”。
- 高内聚:类的内部数据操作细节自己完成,不允许外部干涉;
- 低耦合:仅对外暴露少量的方法用于使用。
隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性,提高程序的安全性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装的设计思想。
3.2 代码
Gril类
public class Gril {
// 属性
private int age; // private表示私有属性,只能在内部访问
// 封装思想的使用:
// 给age提供一个赋值方法:
public void setAge(int age) {
if (age > 30) {
this.age = 18;
} else {
this.age = age;
}
}
// 给age提供一个读取的方法
public int getAge(){
return age;
}
}
Test对象调用Gril类
public class Test {
public static void main(String[] args) {
// 创建对象
Gril g = new Gril();
g.setAge(18);
System.out.println(g.getAge());
}
}
3.3 上述封装代码的解释
上述代码以属性为案例进行封装:
(1)将属性私有化,被private修饰--》加入权限修饰符(一旦加入了权限修饰符,其他人就不能随意的获取这个属性)
(2)提供public修饰的方法让别人来访问/使用
(3)即使外界可以通过方法来访问属性了,但是也不能随意访问,因为程序员可以在方法中加入限制条件。
四、面向对象(继承)
4.1 类是对对象的抽象
4.2 继承是对类的抽象
4.3 继承的格式和好处
(1)继承的格式
子类 extends 父类
public class student extends Person { }
(2)继承的好处
- 提高了代码的复用性;
- 便于代码的扩展;
- 为了多态的使用,是多态使用的前提
4.4 代码示例
Person继承类
public class Person {
// 父类的公共属性:
private int age;
private String name;
private double height;
//父类的公共方法:
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
// 吃饭
public void eat() {
System.out.println("人类可以吃饭!!");
}
//睡觉
public void sleep() {
System.out.println("人类可以睡觉!!");
}
//喊叫
public void shout() {
System.out.println("人类可以喊叫!!");
}
}
Student类
public class Student extends Person {
// 定义子类额外的、扩展的属性
private int sno;
// 定义子类额外的、扩展的方法
public int getSno() {
return sno;
}
public void setSno(int sno) {
this.sno = sno;
}
// 学习:
public void study() {
System.out.println("学生可以学习");
}
}
Test对象
public class Test {
public static void main(String[] args) {
// 定义一个子类具体的对象:
Student s = new Student();
s.setSno(10000);
s.setAge(18);
s.setName("张三");
s.setHeight(180.3);
s.study();
s.eat();
s.shout();
s.sleep();
}
}
4.5 方法的重写
方法的重写是基于继承来的
方法重写的定义:
发生在子类和父类中,当子类对父类提供的方法不满意的时候,要对父类的方法进行重写。
一旦子类对父类的方法进行了重写,对象访问的时候,就只能访问到子类的方法(就近原则)。
方法的重写有严格的格式要求:
子类的方法名和父类必须一致,参数列表(个数,类型,顺序)也要和父类一致。
代码
Person继承类
public class Person {
public void eat(){
System.out.println("人可以吃饭");
}
}
Student类
public class Student extends Person {
// 方法的重写
public void eat(){
System.out.println("我喜欢吃烧烤");
}
}
Test对象
public class Test {
public static void main(String[] args) {
// 创建一个Student具体的对象
Student s = new Student();
s.eat();
}
}
面试常问:
重载和重写有什么区别?
重载:在同一个类中,当方法名相同,形参列表不同的时候,多个方法构成了重载。
重写:在不同的类中,子类对父类提供的方法不满意,对父类的方法进行重写。
五、面向对象(多态)
5.1 多态的概念
多态:通俗来所,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。同一种行为,不同的子类呈现出来的状态是不同的。
ps:多态跟属性无关,多态指的是方法的多态,而不是属性的多态。
5.2 多态的三要素和好处
多态三要素:继承、重写、父类引用指向子类对象
多态的好处:提高代码扩展性
// 这里没太理解,而且比较乱,可以看一下项目中的java10下面的示例
六、异常处理
6.1 什么是异常
异常就是在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序。
- 所需要的文件找不到
- 网络连接不同或中断
- 算术运算错(被零除...)
- 数组下标越界
- 装载一个不存在的类或者对null对象操作
- 类型转换异常
- ........
Java提供异常处理机制。它将异常处理代码和业务代码分离,使程序更优雅,更好的容错性,高健壮性。
Java的异常处理是通过5个关键字来实现的:try、catch、finally、throw、throws
6.2 程序中异常演示
6.3 try-catch-finally
public static void main(String[] args) {
try {
// 求两个数的商
int num1 = 12;
int num2 = 2;
System.out.println("两个数的商为:"+ num1/num2);
} catch (Exception ex){
System.out.println("你的程序出现了错误"+ ex);
} finally {
System.out.println("程序无论是否出现异常,这里的逻辑都必须执行");
}
System.out.println("上面是两个数相除的逻辑案例1");
}
try-catch执行情况
情况1:try块中代码没有出现异常
不执行catch块代码,执行catch块后边的代码
情况2:try块中代码出现异常,catch中异常类型匹配(相同或者父类)
Java会生成相应的异常对象,Java系统寻找匹配的catch块,执行catch块后面的代码。try块中尚未执行的语句不会执行。
情况3:try块代码出现异常,catch中异常类型不匹配
不执行catch块代码,不执行catch块后面的代码,程序会中断运行
catch块中如何处理异常
其中一种方式:自定义内容输出
6.4 throw/throws
throw/throws的使用
public class Test02 {
public static void main(String[] args) {
try {
devide();
} catch (Exception e) {
System.out.println("在调用时处理异常");
}
}
// 提取一个方法:两个数相除操作
public static void devide() throws Exception {
int num1 = 12;
int num2 = 0;
if(num2 == 0){
// 人为制造一个异常
/*
* 第一种抛异常的方式:
try {
throw new Exception();
} catch (Exception e) {
throw new RuntimeException(e);
}
*/
throw new Exception();
}
System.out.println("两个数的商是" + num1/num2);
}
}
throw和throws的区别
(1)位置不同
throw:方法内部
throws:方法的签名处,方法的声明处
(2)内容不同:
throw+异常对象
throws+异常的类型
(3)作用不同:
throw:异常出现的源头,制造异常。
throws:在方法的声明处,告诉方法的调用者,这个方法中可能会出现我声明的这些异常。然后调用者对这个异常进行处理:要么自己处理,要你再继续向外抛出异常。
七、集合
7.1 对比数组的缺点引入集合
(1)数组一旦指定了长度,那么长度就被确定了,不可以更改。
(2)删除、增加元素效率低(如果改变数组中其中一项,后面的项都要跟着变)
(3) 数组中实际元素的数量是没法获取到的,没有提供对应的方法或者属性来获取。
(4)数组存储:有序,可重复,对于无序的,不可重复的场合数组不能满足要求。
7.2 集合体系预览
7.3 ArrayList集合的使用
public static void main(String[] args) {
// 定义一个集合
ArrayList<String> list = new ArrayList<String>();
// 增加元素:
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
System.out.println(list); // [aaa, bbb, ccc, ddd]
// 删除元素:
list.remove("ccc");
System.out.println(list); // [aaa, bbb, ddd]
// 修改元素:
list.set(0, "eee");
System.out.println(list); // [eee, bbb, ddd]
// 查看元素:
System.out.println(list.get(0)); // eee
// 遍历当前集合
// 使用普通的for循环
for (int i = 0; i < list.size()-1; i++) {
System.out.println(list.get(i));
}
}
增加元素 | list.add("aaa"); |
删除元素 | list.remove("ccc"); |
修改元素 | list.set(0, "eee"); |
查找元素 | System.out.println(list.get(0)); |
遍历元素 | for (int i = 0; i < list.size()-1; i++) { |
八、项目总结实战
8.1 需求设计
项目名称:小张书城
项目需求设计:
项目任务 | 涉及技能点 |
---|---|
1、展示书籍 2、上新书籍 3、下架书籍 4、推出应用 |
用户交互-键盘录入 分支结构、循环结构 面向对象思维封装对象(如何合理定义类) 集合的使用 |
8.2 项目代码实现
Books集合
public class Books {// 书籍相关
// 书籍类的 属性
// private修饰符:只允许内部访问,外部无法访问该属性
// 书籍编号
private int bNo;
// 书籍名称
private String bName;
// 书籍作者
private String bAuthor;
//快捷键:alt + insert 快速创建get和set方法
public int getbNo() {
return bNo;
}
public void setbNo(int bNo) {
this.bNo = bNo;
}
public String getbAuthor() {
return bAuthor;
}
public void setbAuthor(String bAuthor) {
this.bAuthor = bAuthor;
}
public String getbName() {
return bName;
}
public void setbName(String bName) {
this.bName = bName;
}
// 构造器
public Books(int bNo, String bName, String bAuthor) {
this.bNo = bNo;
this.bName = bName;
this.bAuthor = bAuthor;
}
// 空构造器
public Books() {
}
}
Test对象
package com.study.java13;
import java.awt.print.Book;
import java.util.ArrayList;
import java.util.Scanner; // 告诉程序这个类在什么位置
/*
【小张书城】项目功能规划:
1.展示书籍
2.上新书籍
书籍信息:书籍编号 书籍名称 书籍作者
01 小张的Java之路 小张快跑 ----》 封装成一个具体的书籍对象 ---》类:书籍
3.下架书籍
4.退出应用
*/
public class Test {
public static void main(String[] args) {
// 创建一个集合:用于存放相同的个体(列表用来存放书籍)--》书籍对象 --》注意作用范围:将list放在循环外面
ArrayList list = new ArrayList(); // 空集合
while (true){
// 打印菜单:
System.out.println("-------欢迎来到【小张书城】-------");
System.out.println("1.展示书籍");
System.out.println("2.上新书籍");
System.out.println("3.下架书籍");
System.out.println("4.退出应用");
// 借助Scanner类:
Scanner sc = new Scanner(System.in); // 扫描键盘录入事件类
// 给一个友好的提示
System.out.println("请录入你想要执行的功能的序号:");
// 利用键盘,录入序号:
int choice = sc.nextInt(); // 接收键盘录入的事件
// 根据choice录入的功能序号,进行后续的判断
if(choice == 1){
System.out.println("<展示书籍>");
// 展示书籍(对集合进行遍历查看)
for (int i = 0; i < list.size(); i++) {
Books b = (Books)(list.get(i)); // Java 语言中的类型转换
System.out.println(b.getbNo() + "------" + b.getbName() + "------" + b.getbAuthor() + "------");
}
}
if(choice == 2){
System.out.println("<上新书籍>");
// 从键盘录入书籍信息
System.out.println("请录入书籍编号:");
int bNo = sc.nextInt(); // 获取家键盘int类型数据
System.out.println("请录入书籍名称:");
String bName = sc.next(); //获取家键盘String类型数据
System.out.println("请录入书籍作者:");
String bAuthor = sc.next(); //获取家键盘String类型数据
// 每上新一本书,就要创建一个书籍对象
Books b = new Books();
b.setbNo(bNo);
b.setbName(bName);
b.setbAuthor(bAuthor);
list.add(b); // 添加个体到集合中去
}
if(choice == 3){
System.out.println("<下架书籍>");
// 录入要下架的书籍的编号
System.out.println("请录入你要下架的书籍的编号:");
int deNo = sc.nextInt();
// 下架编号对应的书籍
for (int i = 0; i < list.size(); i++) {
Books b = (Books)(list.get(i));
if(b.getbNo() == deNo){ // 如果遍历的书籍编号和录入的要删除的书籍编号一致,那么从集合中移除该书籍即可
list.remove(b);
System.out.println("书籍下架成功");
break; // 如果下架成功,就停止遍历,不需要后续的遍历
}
}
}
if(choice == 4){
System.out.println("<退出应用>");
break; // 停止正在执行的循环
}
}
}
}