1、 初识面向对象
属性+方法=类 物以类聚
面向对象编程本质:以类的方式组织代码,以对象的方式组织(封装)数据
面向对象三大特性:封装 继承 多态
2、 方法回顾和加深
1. 方法的创建
package com.fj.oop.demo01;
//Demo01类
public class Demo01 {
//main方法
public static void main(String[] args) {
}
/*
修饰符 返回值类型 方法名(...){
方法体
return 返回值;
}
*/
public String sayHello() {
return "hello,world";
}
public int max(int a, int b) {
return a > b ? a : b;//三元运算符
}
}
2. static 方法和普通方法调用区别
- student 类
package com.fj.oop.demo01;
//学生类
public class Student {
//方非静态法
public void say(){
System.out.println("学生说话了");
}
}
- 引用
package com.fj.oop.demo01;
public class Demo02 {
public static void main(String[] args) {
//实例化这个类 new
//对象类型 对象名 = 对象值;写完new Student(); 用alt + enter 快捷键可以直接出来前面的Student student =
Student student = new Student();
//和类一起加载,可以直接调用
a();
//new 实例化之后才存在,必须先new
Demo02 demo02 = new Demo02();
demo02.b();
}
//和类一起加载
public static void a(){
}
//new 实例化之后才存在
public void b(){
}
}
3. 形参和实参
package com.fj.oop.demo01;
public class Demo03 {
public static void main(String[] args) {
// 1,3 实参
int add = Demo03.add(1,3);
System.out.println(add);//4
}
//int a, int b 形参
public static int add(int a, int b){
return a + b;
}
}
4. 值传递
package com.fj.oop.demo01;
//值传递
public class Demo04 {
public static void main(String[] args) {
int a = 1;
System.out.println(a);//1
change(a);
System.out.println(a);//1
}
public static void change(int a) {
a = 10;
}
}
5. 引用传递:对象,本质还是值传递
package com.fj.oop.demo01;
//引用传递:对象,本质还是值传递
public class Demo05 {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);//null
change(person);
System.out.println(person.name);//ddd
}
public static void change(Person p) {
//Person 是一个对象,指向的是具体的人,可以改变属性
p.name = "ddd";
}
}
//定义一个person类,有一个属性:name
class Person {
String name;//null
}
3、 对象的创建和分析
1. 对象的创建
- Student类创建
package com.fj.oop.demo02;
//学生类
public class Student {
//属性:字段
String name;
int age;
//方法
public void study(){
System.out.println(this.name+"学生在学习");
}
}
- Application 实例化类的创建
一个类,可以实例化无数个对象
package com.fj.oop.demo02;
//一个项目应该只存一个main方法
public class Application {
public static void main(String[] args) {
//类:抽象的,需要实例化
//类实例化后会返回一个自己的对象
//student,student1对象就是一个Student类的具体实例
Student student = new Student();
Student student1 = new Student();
student.name = "小米";
student.age = 12;
System.out.println(student.name);
System.out.println(student.age);
System.out.println("========================");
student1.name = "小李";
student1.age = 18;
System.out.println(student1.name);
System.out.println(student1.age);
}
}
2. 构造方法
构造方法特点:
-
必须和类的名字相同
-
必须没有返回值,也不能写void
-
Person 类说明
package com.fj.oop.demo02;
//一个类什么都不写,他也会存在一个方法(构造方法)
public class Person {
//显示的定义构造器
String name;
//实例化初始值
//1. 使用new关键字,本质是在调用构造器
//alt+insert 默认生成构造器
public Person() {
this.name = "sss";
}
//2. 有参构造:一旦定义了有参构造,无惨就必须显示定义
public Person(String name) {
this.name = name;
}
/*
构造器:
1. 和类名相同
2. 没有返回值
作用:
1. new 本质在调用构造方法
2. 初始化对象的值
注意:
1. 定义有参构造之后,如果想使用无参构造,显示的定义一个无参构造
alt+ insert 快捷键
*/
}
调用构造方法
package com.fj.oop.demo02;
//一个项目应该只存一个main方法
public class Application {
public static void main(String[] args) {
//类:抽象的,需要实例化
//new 实例化一个无参构对象
Person person = new Person();
System.out.println(person.name);//sss
//new 实例化有参构造
Person person1 = new Person("DDD");
System.out.println(person1.name);//DDD
}
}
- 内存分析
5. 总结
1. 类与对象
类是一个模板:抽象的 ,对象是一个具体实例:具体的
2. 方法
定义,调用
3. 对像的引用
引用类型:基本类型(8种)
对象是通过引用来操作的,栈--->堆(地址)
4. 属性:字段field 成员变量
默认初始化:
数字:0 0.0
char: u0000
boolean: false
引用:null
修饰符 属性类型 属性名=属性值!
5. 对象的创建和使用
-- 必须使用new关键字创造对象,构造器 Person person = new Person()
-- 对象的属性 person.name
-- 对象的方法 person->sleep()
6. 类
静态的属性 属性
动态的行为 方法
四、 面向对象三大特性
1. 封装
package com.fj.oop.demo04;
//类 alt+insert->Getter and Setter 自动生成get set方法
/*
1. 提高程序的安全性,保护数据
2. 隐藏代码的实现细节
3. 统一接口
4. 系统可维护性提高了
*/
public class Student {
//属性私有,除了当前类不能被访问获取
//名字
private String name;
//学号
private int id;
//性别
private char sex;
//年龄
private int age;
//学习()
//睡觉()
//提供一些可以操作的属性的方法~
//提供一些public 的get,set方法
//get 获得这个数据
public String getName() {
return this.name;
}
//set 设置这个数据
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 120 || age < 0) {//不合法
this.age = 3;
} else {
this.age = age;
}
}
}
结果:
package com.fj.oop;
import com.fj.oop.dem003.Pet;
import com.fj.oop.demo04.Student;
public class Application {
public static void main(String[] args) {
/********************************************************
* 总结类和对象
* ******************************************************
*/
/*
1. 类与对象
类是一个模板:抽象的 ,对象是一个具体实例:具体的
2. 方法
定义,调用
3. 对像的引用
引用类型:基本类型(8种)
对象是通过引用来操作的,栈--->堆(地址)
4. 属性:字段field 成员变量
默认初始化:
数字:0 0.0
char: u0000
boolean: false
引用:null
修饰符 属性类型 属性名=属性值!
5. 对象的创建和使用
-- 必须使用new关键字创造对象,构造器 Person person = new Person()
-- 对象的属性 person.name
-- 对象的方法 person->sleep()
6. 类
静态的属性 属性
动态的行为 方法
*/
/********************************************************
* demo04 Student
* ******************************************************
*/
Student student = new Student();
//名称
student.setName("张三");
String name = student.getName();
System.out.println(name);
//年龄
student.setAge(999);//不合法
System.out.println(student.getAge());
System.out.println("demo04 Student END=============================");
}
}
2. 继承
- 继承实例:
父类实例
package com.fj.oop.demo05;
//继承 父类
//默认继承object
public class Person {
//public 公共的
//private 私有的
private int money = 10_0000_0000;
public void say() {
System.out.println("说了一句话");
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
子类实例
package com.fj.oop.demo05;
//老师 子类
public class Teacher extends Person {
}
实例化类
package com.fj.oop;
import com.fj.oop.demo05.Teacher;
public class Application {
public static void main(String[] args) {
/********************************************************
* demo05 Person父类 Student、Teacher 子类 继承
* ******************************************************
*/
Teacher teacher = new Teacher();
teacher.say();
System.out.println("demo05 Person父类 Student、Teacher 子类 继承 END=============================");
}
}
结果:
说了一句话
demo05 Person父类 Student、Teacher 子类 继承 END=============================
- Super详解
- super注意点:
* 1. Super调用父类的构造方法,必须在构造方法的第一个
* 2. super必须只能出现在之类的方法或者构造方法中
* 3. super 和this 不能同事调用构造方法 - vs this:
* 代表的对象不同:
* this:本身调用者这个对象
* super:代表父类对象的应用 - 前提
* this:没有继承也可以使用
* super:只能在继承条件才可以使用 - 构造方法
* this():代表本类的构造
* super():父类的构造
子类实例:
package com.fj.oop.demo05;
//学生 子类
public class Student extends Person {
private String name = "qqq";
public Student(){
System.out.println("Student无参执行了");
}
public void print(){
System.out.println("Student");
}
public void test1(String name){
//调用当前方法
print();
//调用当前方法
this.print();
//调用父类的方法
super.print();
}
public void test(String name){
System.out.println(name);
System.out.println(this.name);
//super 调用父类的参数
System.out.println(super.name);
}
}
父类实例
package com.fj.oop.demo05;
//继承 父类
//默认继承object
public class Person {
public Person(){
System.out.println("Person无参执行了");
}
protected String name = "郑丽";
public void print(){
System.out.println("Person");
}
}
调用:
package com.fj.oop;
import com.fj.oop.demo05.Person;
public class Application {
public static void main(String[] args) {
/********************************************************
* demo05 Person父类 Student、Teacher 子类 继承
* super注意点:
* 1. Super调用父类的构造方法,必须在构造方法的第一个
* 2. super必须只能出现在之类的方法或者构造方法中
* 3. super 和this 不能同事调用构造方法
* vs this:
* 代表的对象不同:
* this:本身调用者这个对象
* super:代表父类对象的应用
* 前提
* this:没有继承也可以使用
* super:只能在继承条件才可以使用
* 构造方法
* this():代表本类的构造
* super():父类的构造
*
* ******************************************************
*/
com.fj.oop.demo05.Student student1 = new com.fj.oop.demo05.Student();
student1.test("dd");
System.out.println("demo05 Person父类 Student、Teacher 子类 继承 END=============================");
}
}
结果:
Person无参执行了
Student无参执行了
dd
qqq
郑丽
demo05 Person父类 Student、Teacher 子类 继承 END=============================
- 方法重写
- 静态方法和非静态方法区别很大
* 静态方法:方法的调用只和左边,定义的数据类型有关
* 非静态方法:重写 - 重写总结: 需要有继承关系,子类重写父类的方法,重写不能是私有的
* 1. 方法名必须相同
* 2. 参数列表必须相同
* 3.修饰符:范围可以扩大,但是不能缩小,public->protected->default->private
* 4.抛出的异常:范围,可以被缩小,但不能扩大 - 重写,子类的方法和父类必须要一致,方法体不同
- 为什么需要重写:
* 1.父类的功能,子类不一定需要,或者不一定满足
* alt+insert:override
静态方法重写:方法的调用只和左边,定义的数据类型有关
静态方法父类:
package com.fj.oop.demo05;
public class B {
public static void test(){
System.out.println("B=>test()");
}
}
静态方法子类:
package com.fj.oop.demo05;
//a 继承 b
public class A extends B {
public static void test(){
System.out.println("A=>test()");
}
}
静态方法调用
package com.fj.oop;
import com.fj.oop.demo05.A;
import com.fj.oop.demo05.B;
public class Application {
public static void main(String[] args) {
/********************************************************
* demo05 A B 重写
* 静态方法和非静态方法区别很大
* 静态方法:方法的调用只和左边,定义的数据类型有关
* 非静态方法:重写
* 重写总结:
* 需要有继承关系,子类重写父类的方法
* 1. 方法名必须相同
* 2. 参数列表必须相同
* 3.修饰符:范围可以扩大,但是不能缩小,public->protected->default->private
* 4.抛出的异常:范围,可以被缩小,但不能扩大
* 重写,子类的方法和父类必须要一致,方法体不同
* 为什么需要重写:
* 1.父类的功能,子类不一定需要,或者不一定满足
* alt+insert:override
*
* ******************************************************
*/
A a = new A();//调用的a类
a.test();//A=>test()
//a继承b,a的引用指向了b,父类的引用指向子类
//b是父类,a是子类
B b = new A();//调用的b类
b.test();//B=>test()
System.out.println("demo05 A B 重写 END=============================");
}
}
结果:父类的引用指向子类,方法的调用只和左边,定义的数据类型有关
A=>test()
B=>test()
demo05 A B 重写 END=============================
非静态方法重写:重写,alt+insert:Override
非静态方法重写父类
package com.fj.oop.demo05;
public class B {
public void test(){
System.out.println("B=>test()");
}
}
非静态方法重写子类
package com.fj.oop.demo05;
//a 继承 b
public class A extends B {
//alt+insert:Override 自动生成
@Override
public void test() {
//注释掉调用父类,重写父类的方法
//super.test();
System.out.println("A=>test()");
}
}
非静态方法调用
package com.fj.oop;
import com.fj.oop.demo05.A;
import com.fj.oop.demo05.B;
public class Application {
public static void main(String[] args) {
/********************************************************
* demo05 A B 重写
* 静态方法和非静态方法区别很大
* 静态方法:方法的调用只和左边,定义的数据类型有关
* 非静态方法:重写
* 重写总结:
* 需要有继承关系,子类重写父类的方法
* 1. 方法名必须相同
* 2. 参数列表必须相同
* 3.修饰符:范围可以扩大,但是不能缩小,public->protected->default->private
* 4.抛出的异常:范围,可以被缩小,但不能扩大
* 重写,子类的方法和父类必须要一致,方法体不同
* 为什么需要重写:
* 1.父类的功能,子类不一定需要,或者不一定满足
* alt+insert:override
*
* ******************************************************
*/
A a = new A();//调用的a类
a.test();//A=>test()
//b是父类,a是子类
B b = new A();//调用的a类
b.test();//A=>test()
System.out.println("demo05 A B 重写 END=============================");
}
}
非静态方法结果:重写了父类,调用的子类
A=>test()
A=>test()
demo05 A B 重写 END=============================
3. 多态
- 一个对象的实际类型是确定的
* new Student()
* new Person() - 可以指向的引用类型就不确定:父类的引用指向子类
- 多态的注意事项:
* 1.多态是方法的多态,属性没有多态
* 2. 父类和子类,有联系
* 3. 存在条件:继承关系,方法需要重写,父类引用指向子类对象 father f1 = new son()
* 4. 以下不能重写和实现多态
* static 方法,属于类,他不属于实例
* final 常量;
* private 方法
- 实例说明
父类实例
package com.fj.oop.demo06;
public class Person {
//父类的方法
public void run(){
System.out.println("run");
}
}
子类实例
package com.fj.oop.demo06;
public class Student extends Person {
//重写父类的方法
@Override
public void run() {
System.out.println("son");
}
//子类独有的方法
public void eat(){
System.out.println("eat");
}
}
调用
package com.fj.oop;
import com.fj.oop.demo06.Person;
public class Application {
public static void main(String[] args) {
/**************************************************************
* demo06 多态
* 一个对象的实际类型是确定的
* new Student()
* new Person()
* 可以指向的引用类型就不确定:父类的引用指向子类
* 多态的注意事项:
* 1.多态是方法的多态,属性没有多态
* 2. 父类和子类,有联系
* 3. 存在条件:继承关系,方法需要重写,父类引用指向子类对象 father f1 = new son()
* 4. 以下不能重写和实现多态
* static 方法,属于类,他不属于实例
* final 常量;
* private 方法
* ************************************************************
*/
//Student 能调用的方法都是自己或者继承父类的
com.fj.oop.demo06.Student s1 = new com.fj.oop.demo06.Student();
//Person 父类型,可以指向子类,但是不能调用子类独有的方法
Person s2 = new com.fj.oop.demo06.Student();
Object S3 = new com.fj.oop.demo06.Student();
s2.run();//son子类重写了父类的方法,执行子类的方法
s1.run();//son子类重写了父类的方法,执行子类的方法
//对象能执行那些方法,主要看对象左边的类型,和右边关系不打
s1.eat();//eat
//s2.eat();//报错,Person 父类型,可以指向子类,但是不能调用子类独有的方法
System.out.println("demo06 多态 END=============================");
}
}
结果
son
son
eat
demo06 多态 END=============================
- instanceof
判断父类对象是否为子类对象的实例
// object->String
// object->person->student
// object->person->Teacher
// System.out.println(x instanceof y);//x:某类的对象引用。y:某个类。
Object object = new com.fj.oop.demo06.Student();
System.out.println(object instanceof com.fj.oop.demo06.Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof String);//false
Person person = new com.fj.oop.demo06.Student();
System.out.println(person instanceof com.fj.oop.demo06.Student);//TRUE
System.out.println(person instanceof Person);//TRUE
System.out.println(person instanceof Object);//TRUE
System.out.println(person instanceof Teacher);//FALSE
System.out.println("demo06 instanceof END=============================");
- 类型转换
- 类型直接的转化:基本类型转换 高低 64 32 16 父类->子类, 子类转父类可能会丢失方法
* 1. 父类引用指向之类的对象
* 2. 把子类转换为父类,向上转型
* 3. 把父类转换为子类,向下转型,强制转换
* 4. 方便方法的调用,减少重复的代码
父类实例 :
package com.fj.oop.demo06;
public class Person {
//父类的方法
public void run(){
System.out.println("run");
}
}
子类实例:
package com.fj.oop.demo06;
public class Student extends Person {
//重写父类的方法
@Override
public void run() {
System.out.println("son");
}
//子类独有的方法
public void eat(){
System.out.println("eat");
}
public void go(){
System.out.println("go");
}
}
调用
package com.fj.oop;
import com.fj.oop.demo06.Person;
import com.fj.oop.demo06.Teacher;
public class Application {
public static void main(String[] args) {
/**************************************************************
* demo06 类型转换
* 类型直接的转化:基本类型转换 高低 64 32 16 父类->子类
* 子类转父类可能会丢失方法
* 1. 父类引用指向之类的对象
* 2. 把子类转换为父类,向上转型
* 3. 把父类转换为子类,向下转型,强制转换
* 4. 方便方法的调用,减少重复的代码
**************************************************************
*/
//高 低
// Person obj 只能调用Person和Student共同拥有的方法,Student独有的go, Person obj 调用不了
Person obj = new com.fj.oop.demo06.Student();
// student 将Person obj这个对象转换为student类型,我们就可以使用student类型的方法了,
com.fj.oop.demo06.Student student6 = (com.fj.oop.demo06.Student) obj;
student6.go();
}
}
- static
静态方法或属性可以直接调用,非静态方法或者属性必须实例化后调用
package com.fj.oop.demo07;
public class Student {
private static int age;//静态变量
private double score;//非静态变量
public void run(){
}
public static void go(){
}
public static void main(String[] args) {
//静态属性可以直接调用
System.out.println(Student.age);
//静态属性可以直接调用
System.out.println(age);
//静态属性可以直接调用
Student.go();
go();
//非静态属性必须实例化后调用
Student s1 = new Student();
System.out.println(s1.age);
System.out.println(s1.score);
//非静态方法必须实例化后调用
new Student().run();
}
}
代码块和构造方法的介绍
静态代码块:第一个执行,只执行一次
匿名代码块:第二个执行,每次实例化都执行,可以用来赋初始值
构造方法:第三个个执行,每次都执行
package com.fj.oop.demo07;
public class Person
{
//2 赋初始值
{
//代码块(匿名代码块)
System.out.println("匿名代码块");
}
//1 只执行一次
static {
//静态代码块
System.out.println("静态代码块");
}
public Person() {
System.out.println("构造方法");
}
//3
public static void main(String[] args) {
Person person = new Person();
System.out.println("===========");
Person person1 = new Person();
}
}
结果
静态代码块
匿名代码块
构造方法
===========
匿名代码块
构造方法
Process finished with exit code 0
静态导入包介绍
静态导入包导入方法,可以直接调用random,不用Math.random()
package com.fj.oop.demo07;
// 静态导入包导入方法,可以直接调用random,不用Math.random()
import static java.lang.Math.random;
import static java.lang.Math.PI;
public class Test {
public static void main(String[] args) {
// System.out.println(Math.random());
System.out.println(random());
System.out.println(PI);
}
}
结果:
0.9167222619701163
3.141592653589793
Process finished with exit code 0
- final
被final修饰的类就不能被继承了
package com.fj.oop.demo07;
//被final修饰的类就不能被继承了
public final class Person
{
public static void main(String[] args) {
}
}
五、 抽象类和接口
1.普通类:只有具体实现。单继承,继承关键字:extends。声明类的关键字是:class
public class A {} public class B extends A {}
2. 抽象类:具体实现和规范(抽象方法)都有。单继承,继承关键字:extends。声明抽象类关键字是:class,修饰符是:abstract
public abstract class Action {}
3. 接口 : 只有规范,自己无法写方法,约束和实现分离:面向接口编程,接口的本质是契约。多继承,继承关键字:implements。声明接口的关键字是:interface
public interface UserService {}
public interface TimeService {}
public class UserServiceImpl implements UserService,TimeService{}
1. 抽象类
abstract 修饰符是定义抽象类
1. 抽象类不能new,只能靠子类去实现他:约束
2. 抽象类可以写普通方法
3. 抽象方法必须在抽象类中,如果一个类中有抽象方法,这个类必须是抽象类
抽象的抽象:约束
alt+insert:implement Methods快捷键 子类继承抽象类时,可以选择生成父类的抽象方法
抽象类实例:
package com.fj.oop.demo08;
//abstract 抽象类 extends: java类、抽象类都是单继承(接口可以多继承)
public abstract class Action {
//约束,有人帮我们实现
//abstract ,抽象方法,只有方法名字,没有方法的实现
public abstract void doSomething();
// 1. 抽象类不能new,只能靠子类去实现他:约束
// 2. 抽象类可以写普通方法
// 3. 抽象方法必须在抽象类中,如果一个类中有抽象方法,这个类必须是抽象类
// 抽象的抽象:约束
//思考题? 不能new,但是有在构造器、静态方法 存在的意义:用来统
}
子类继承实现
package com.fj.oop.demo08;
// 抽象累的所有方法,继承了他的子类,都必须要实现他的方法
public class A extends Action {
//alt+insert:implement Methods快捷键可以重载父类的抽象方法
@Override
public void doSomething() {
}
}
2. 接口
作用:
1.是一种约束
2.定义一些方法,让不同的人实现
3. 接口中的方法都是public abstract
4. 所有的常量都是public static final,这个是静态常量
5. 接口不能被实例化,接口中没有构造方法,接口不是类,所以没有构造方法
6. implements实现多接口继承
7. 必须要重写接口中的方法
抽象类UserService
package com.fj.oop.demo09;
//interface 定义关键字,接口都需要有实现类
public interface UserService {
//接口中的所有定义其实都是抽象的,都是public abstract
// public abstract void run();默认是这种,简略写void run();
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
抽象类TimeService
package com.fj.oop.demo09;
public interface TimeService {
void timer();
}
子类继承实现
package com.fj.oop.demo09;
// 普通类,抽象类:extends 单继承
//类可以实现接口 implements 继续多接口
// 实现了接口的类,就需要重写接口中的方法
//多继承:利用接口实现多继承
public class UserServiceImpl implements UserService,TimeService{
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void timer() {
}
}
六、 内部类及OOP实战
1. 内部类
外部类的类中在创建一个内部类
package com.fj.oop.demo10;
//外部类
public class Outer {
private int id = 10;
public void out() {
System.out.println("外部类的方法");
}
public class Inner {
public void in() {
System.out.println("内部类的方法");
}
//获得外部类的私有属性
public void getID(){
System.out.println(id);
}
}
}
调用
//外部类
Outer outer = new Outer();
//通过外部类实例化内部类
Outer.Inner inner = outer.new Inner();
//获取内部类的方法
inner.in();
//通过内部类获取外部类的私有属性
inner.getID();
结果
内部类的方法
10
2. 多个class类
一个java类中可以有多个class类,但是只能有一个public class
package com.fj.oop.demo10;
//外部类
public class Outer {
}
// 一个java类中可以有多个class类,但是只能有一个public class
class A{
public static void main(String[] args) {
}
}
3. 局部内部类
package com.fj.oop.demo10;
//外部类
public class Outer {
//局部内部类
public void method(){
class Inner{
//局部内部类
public void in(){
}
}
}
}
4. 匿名对象(内部)类
package com.fj.oop.demo10;
public class Text {
public static void main(String[] args) {
//Apple apple = new Apple();
//没有名字初始化类,匿名对象类,不用将实例保存到变量中
new Apple().eat();
//匿名
UserService userService = new UserService() {
@Override
public void hello() {
}
};
}
}
class Apple {
public void eat() {
System.out.println("1");
}
}
//接口
interface UserService {
void hello();
}
七、异常机制
1. 什么是异常
影响正常的程序执行流程
2. 异常体系结构
error:错误,致命性的
exception:运行时异常,抛出异常
3. Java异常处理机制
抛出异常
捕获异常
异常处理五个关键字:
try、catch、finally、throw、throws
finally 可以不要,假设io,资源关闭需要有finally
要捕获多个异常:从小到大
捕获异常代码实例
package com.fj.exception;
public class Demo01 {
public static void main(String[] args) {
// new Demo01().a();
int a = 1;
int b = 0;
try {//监控区域
System.out.println(a/b);
}catch (ArithmeticException e){//catch 捕获异常
System.out.println(e);
}finally {//处理善后工作,无论有没有异常finally都会被执行
System.out.println("finally");
}
//finally 可以不要,假设io,资源关闭需要有finally
//要捕获多个异常:从小到大
System.out.println("=======================");
try {//监控区域
new Demo01().a();
}catch (Error e){//catch 捕获异常
System.out.println("Error");
}catch (Exception e){//catch 捕获异常
System.out.println("Exception");
}catch (Throwable t){//catch 捕获异常
System.out.println("Throwable");
}finally {//处理善后工作,无论有没有异常finally都会被执行
System.out.println("finally");
}
}
public void a() {
b();
}
public void b() {
a();
}
}
4. 处理异常
主动抛出异常代码实例
package com.fj.exception;
public class Test {
public static void main(String[] args) {
try {
new Test().test(1, 0);
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
//假设在方法中,处理不了这个异常,方法上抛出异常
public void test(int a, int b) throws ArithmeticException {
if (b == 0) {
if (b == 0) {//主动抛出异常 throw throws
throw new ArithmeticException();//主动抛出异常,一般在方法中使用
}
System.out.println(a / b);
}
}
}
5. 自定义异常
- 自定义异常类继承Exception,用toString打印出来
package com.fj.exception.demo02;
//自定义异常类
public class MyException extends Exception{
//传递数字>10;
private int detail;
public MyException(int a){
this.detail=a;
}
//toString:异常的打印信息 alt+insert:toString()
@Override
public String toString() {
return "MyException{" +
"detail=" + detail +
'}';
}
}
调用
package com.fj.exception.demo02;
public class Test {
//可能会存在异常的方法
static void test(int a) throws MyException {
System.out.println("传递的参数为:"+a);
if(a>10){
throw new MyException(a);
}
System.out.println("ok");
}
public static void main(String[] args) {
try {
test(11);
}catch (MyException e){
System.out.println("MyException=>"+e);
}
}
}
结果:
传递的参数为:11
MyException=>MyException{detail=11}
Process finished with exit code 0
6. 总结
思维导图地址:http://naotu.baidu.com/file/aa7cd5cb306562b2d220bd14ca7b525d?token=0ce90d2b3f763a6c
当前链接: 密码为 8w9e
总结图片:
7. 面向对象项目
一. 普通方式完成
- 新建父类
package com.msb.test01;
/**
* 父类:披萨类
*/
public class Pizza {
//属性
private String name;//名称
private int size;//大小
private int price;//价格
//方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
//展示披萨信息:
public String showPizza() {
return "披萨的名称是:" + name + "\n披萨的大小是:" + size + "寸\n披萨的价格是:" + price+"元";
}
//空构造器
public Pizza() {
}
//带参数构造器
public Pizza(String name, int size, int price) {
this.name = name;
this.size = size;
this.price = price;
}
}
- 新建水果披萨子类
package com.msb.test01;
/**
* 水果披萨
*/
public class FruitsPizza extends Pizza{
//属性:
private String burdening;
public String getBurdening() {
return burdening;
}
public void setBurdening(String burdening) {
this.burdening = burdening;
}
//构造器
public FruitsPizza() {
}
//
public FruitsPizza(String name, int size, int price, String burdening) {
super(name, size, price);
this.burdening = burdening;
}
//重写父类的showPizza方法
@Override
public String showPizza() {
return super.showPizza()+"\n你要加入的水果:"+burdening;
}
}
- 新建培根披萨子类
package com.msb.test01;
/**
* 培根披萨
*/
public class BaconPizza extends Pizza{
//属性
private int weight;
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
//构造器
public BaconPizza() {
}
public BaconPizza(String name, int size, int price, int weight) {
super(name, size, price);
this.weight = weight;
}
//重写父类的showPizza方法
@Override
public String showPizza() {
return super.showPizza()+"\n培根的克数是:"+weight+"克";
}
}
- 新建测试类
package com.msb.test01;
import java.util.Scanner;
public class Test {
//这是一个main方法,是程序的入口:
public static void main(String[] args) {
//选中购买的披萨
Scanner sc = new Scanner(System.in);
System.out.println("请选择你要购买的披萨(1.培根披萨 2. 水果披萨):");
int choice = sc.nextInt();//选中
switch (choice) {
case 1: {//添加{}代码块,int size 作用域在当前case1
System.out.println("请录入培根的克数:");
int weight = sc.nextInt();
System.out.println("请录入披萨的大小:");
int size = sc.nextInt();
System.out.println("请录入披萨的价格:");
int price = sc.nextInt();
//将录入的信息封装为培根披萨的对象
BaconPizza bp = new BaconPizza("培根披萨",size,price,weight);
System.out.println(bp.showPizza());
}
break;
case 2: {
System.out.println("请录入你想要加入的水果:");
String burdening = sc.next();
System.out.println("请录入披萨的大小:");
int size = sc.nextInt();
System.out.println("请录入披萨的价格:");
int price = sc.nextInt();
//将录入的信息封装为水果披萨的对象
FruitsPizza fp = new FruitsPizza("水果披萨",size,price,burdening);
System.out.println(fp.showPizza());
}
break;
}
}
}
- 结果
请选择你要购买的披萨(1.培根披萨 2. 水果披萨):
2
请录入你想要加入的水果:
榴莲,芒果
请录入披萨的大小:
12
请录入披萨的价格:
45
披萨的名称是:水果披萨
披萨的大小是:12寸
披萨的价格是:45元
你要加入的水果:榴莲,芒果
二. 工厂模式
- 父类
package com.msb.test01;
/**
* 父类:披萨类
*/
public class Pizza {
//属性
private String name;//名称
private int size;//大小
private int price;//价格
//方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
//展示披萨信息:
public String showPizza() {
return "披萨的名称是:" + name + "\n披萨的大小是:" + size + "寸\n披萨的价格是:" + price+"元";
}
//空构造器
public Pizza() {
}
//带参数构造器
public Pizza(String name, int size, int price) {
this.name = name;
this.size = size;
this.price = price;
}
}
- 水果披萨子类
package com.msb.test01;
/**
* 水果披萨
*/
public class FruitsPizza extends Pizza{
//属性:
private String burdening;
public String getBurdening() {
return burdening;
}
public void setBurdening(String burdening) {
this.burdening = burdening;
}
//构造器
public FruitsPizza() {
}
//
public FruitsPizza(String name, int size, int price, String burdening) {
super(name, size, price);
this.burdening = burdening;
}
//重写父类的showPizza方法
@Override
public String showPizza() {
return super.showPizza()+"\n你要加入的水果:"+burdening;
}
}
- 培根披萨
package com.msb.test01;
/**
* 培根披萨
*/
public class BaconPizza extends Pizza{
//属性
private int weight;
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
//构造器
public BaconPizza() {
}
public BaconPizza(String name, int size, int price, int weight) {
super(name, size, price);
this.weight = weight;
}
//重写父类的showPizza方法
@Override
public String showPizza() {
return super.showPizza()+"\n培根的克数是:"+weight+"克";
}
}
- 工厂类
package com.msb.test01;
import java.util.Scanner;
/**
* 工厂模式
*/
public class PizzaStore {
public static Pizza getPizza(int choice){
Pizza p = null;
Scanner sc = new Scanner(System.in);
switch (choice) {
case 1: {//添加{}代码块,int size 作用域在当前case1
System.out.println("请录入培根的克数:");
int weight = sc.nextInt();
System.out.println("请录入披萨的大小:");
int size = sc.nextInt();
System.out.println("请录入披萨的价格:");
int price = sc.nextInt();
//将录入的信息封装为培根披萨的对象
BaconPizza bp = new BaconPizza("培根披萨",size,price,weight);
//System.out.println(bp.showPizza());
p = bp;
}
break;
case 2: {
System.out.println("请录入你想要加入的水果:");
String burdening = sc.next();
System.out.println("请录入披萨的大小:");
int size = sc.nextInt();
System.out.println("请录入披萨的价格:");
int price = sc.nextInt();
//将录入的信息封装为水果披萨的对象
FruitsPizza fp = new FruitsPizza("水果披萨",size,price,burdening);
//System.out.println(fp.showPizza());
p = fp;
}
break;
}
return p;
}
}
- 调用实现
package com.msb.test01;
import java.util.Scanner;
public class Test {
//这是一个main方法,是程序的入口:
public static void main(String[] args) {
//选中购买的披萨
Scanner sc = new Scanner(System.in);
System.out.println("请选择你要购买的披萨(1.培根披萨 2. 水果披萨):");
int choice = sc.nextInt();//选中
//通过工厂模式,获取披萨
Pizza pizza = PizzaStore.getPizza(choice);
System.out.println(pizza.showPizza());
}
}
- 运行结果
请选择你要购买的披萨(1.培根披萨 2. 水果披萨):
2
请录入你想要加入的水果:
jj,ddd
请录入披萨的大小:
34
请录入披萨的价格:
4
披萨的名称是:水果披萨
披萨的大小是:34寸
披萨的价格是:4元
你要加入的水果:jj,ddd
Process finished with exit code 0