面向过程与面向对象(上) 面向过程与面向对象区别
面向过程:当事件比较简单的时候,利用面向过程,注重的是事件的具体的步骤/过程,注重的是过程中的具体的行为,以函数为最小单位,考虑怎么做
面向对象:注重找“参与者”,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做
案例:人把大象装进冰箱
面向过程
函数1:打开冰箱(){人站在冰箱前,打开冰箱,冰箱开到30度角的时候,冰箱的灯打开了………}
函数2:储存大象(){大象先迈左腿,再迈右退,考虑冰箱能不能装下……}
函数3:关闭冰箱(){人站在冰箱前,关闭冰箱,冰箱开到30度角的时候,冰箱的灯关闭了……….}
面向对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 人{ 打开(冰箱){ 冰箱.打开(); } 存储(大象){ 大象.进入(); } 关闭(冰箱){ 冰箱.关闭(); } } 冰箱{ 打开(){ 1.2 .3 .} 关闭(){} } 柜子{ } 大象{ 进入(冰箱){} }
面向过程 —> 面向对象 , 其实就是由执行者 —> 指挥者的 一个过渡
二者相辅相成,并不是对立的。解决复杂问题,通过面向对象方式便于我们从宏观上把握事物之间复杂的关系、方便我们分析整个系统;具体到微观操作,仍然使用面向过程方式来处理
类和对象的关系
万事万物皆对象
类和对象
一般在写代码的时候先写类,然后在根据类创建对应的对象。
面向对象三个阶段
面向对象分析OOA – Object Oriented Analysis
对象:张三,王五,朱六,你,我
抽取出一个类—-》人类
类里面有什么
动词–》动态特性–》方法
名词–》静态特性–》属性
面向对象设计OOD – Object Oriented Design
先有类,再有对象
类:人类(Person)
对象:zhangsan ,lisi,zhuliu
面向对象编程OOP – Object Oriented Programming
创建类 1 2 3 4 5 6 7 8 9 10 11 12 13 属性用于定义该类或该类对象包含的数据或者说静态特征。属性作用范围是整个类体。 属性定义格式: [修饰符] 属性类型 属性名 = [默认值] ; 方法用于定义该类或该类实例的行为特征和功能实现。方法是类和对象行为特征的抽象。方法很类似于面向过程中的函数。面向过程中,函数是最基本单位,整个程序由一个个函数调用组成。面向对象中,整个程序的基本单位是类,方法是从属于类和对象的。 方法定义格式: [修饰符] 方法返回值类型 方法名(形参列表) { } void 代表没有返回值;方法的作用:重用代码,封装功能,便于修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package com.excepenxi;public class Person { int age ; String name; double height; double weight; public void eat () { int num = 10 ; System.out.println("我喜欢吃饭" ); } public void sleep (String address) { System.out.println("我在" +address+"睡觉" ); } public String introduce () { return "我的名字是:" +name+",我的年龄是:" +age+",我的身高是:" +height+",我的体重是:" +weight; } }
创建对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package com.excepenxi;public class Test { public static void main (String[] args) { Person zs = new Person (); zs.name = "张三" ; zs.age = 19 ; zs.height = 180.4 ; zs.weight = 170.4 ; Person ls = new Person (); ls.name = "李四" ; ls.age = 18 ; ls.height = 170.6 ; ls.weight = 160.5 ; System.out.println(zs.name); System.out.println(ls.age); zs.eat(); ls.eat(); zs.sleep("教室" ); System.out.println(zs.introduce()); } }
局部变量与成员变量的区别
区别1:代码中位置不同
成员变量:类中方法外定义的变量
局部变量:方法中定义的变量 代码块中定义的变量
区别2:代码的作用范围
成员变量:当前类的很多方法
局部变量:当前一个方法(当前代码块)
区别3:是否有默认值
成员变量:有
局部变量:没有
引用数据类型: null
区别4:是否要初始化
成员变量:不需要,不建议初始化,后续使用的时候再赋值即可
局部变量:一定需要,不然直接使用的时候报错
区别5:内存中位置不同
区别6:作用时间不同
成员变量:当前对象从创建到销毁
局部变量:当前方法从开始执行到执行完毕
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package com.excepenxi;public class Student { byte e; short s; int c ; long num2; float f ; double d; char ch; boolean bo; String name; public void study () { int num = 10 ; System.out.println(num); { int a; } int a; if (1 ==3 ){ int b; } System.out.println(c); } public void eat () { System.out.println(c); } public static void main (String[] args) { Student s = new Student (); System.out.println(s.c); System.out.println(s.bo); System.out.println(s.ch); System.out.println(s.d); System.out.println(s.e); System.out.println(s.f); System.out.println(s.name); System.out.println(s.num2); System.out.println(s.s); s.d = 10.4 ; } }
构造器 Person类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.excepenxi;public class Person { public Person () { } String name; int age; double height; public void eat () { System.out.println("我喜欢吃饭" ); } }
Test类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package com.excepenxi;public class Test { public static void main (String[] args) { Person p = new Person (); System.out.println(p.age); System.out.println(p.name); System.out.println(p.height); Person p2 = new Person (); System.out.println(p2.age); System.out.println(p2.name); System.out.println(p2.height); } }
构造器重载 Person类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package com.excepenxi;public class Person { String name; int age; double height; public Person () { } public Person (String name,int age,double height) { this .name = name; this .age = age; this .height = height; } public Person (String a,int b) { name = a; age = b; } public void eat () { System.out.println("我喜欢吃饭" ); } }
Test类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.excepenxi;public class Test { public static void main (String[] args) { Person p = new Person (); Person p2 = new Person ("lili" ,19 ,180.4 ); System.out.println(p2.age); System.out.println(p2.height); System.out.println(p2.name); } }
内存分析 1 2 3 4 5 6 7 public class Person { int id; int age; public static void main (String args[]) { Person p1 = new Person (); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Person { int id; int age; String school; public Person (int a,int b,String c) { id=a; age=b; school=c; } public static void main (String args[]) { Person p = new Person (1 ,20 , "海淀" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 class Person { int id; int age; String school; Person (int a,int b,String c){ id=a; age=b; school=c; } public void setAge (int a) { age=a; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Test { public static void main (String[] args) { Test t = new Test (); int age=40 ; Person tom = new Person (1 ,20 ,"海淀" ); Person jack = new Person (2 ,30 ,"朝阳" ); t.change1(age); t.change2(tom); t.change3(jack); System.out.println(age); System.out.println("id:" +jack.id+",age:" +jack.age+",school:" +jack.school); } public void change1 (int i) { i=3366 ; } public void change2 (Person p) { p=new Person (3 ,22 ,"西城" ); } public void change3 (Person p) { p.setAge(66 ); } }
this的使用
创建对象的过程:
在第一次遇到一个类的时候,对这个类要进行加载,只加载一次
创建对象,在堆中开辟空间
对对象进行初始化操作,属性赋值都是默认的初始值
new关键字调用构造器,执行构造方法,在构造器中对属性重新进行赋值
从上面的效果能够看到:this指代的就是当前对象
this关键字 用法
this可以修饰属性
总结:当属性名字和形参发生重名
的时候,或者 属性名字 和局部变量重名
的时候,都会发生就近原则,所以如果我要是直接使用变量名字的话就指的是离的近的那个形参或者局部变量,这时候如果我想要表示属性的话,在前面要加上:this.修饰
如果不发生重名问题的话,实际上你要是访问属性也可以省略this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.excepenxi;public class Person { int age; String name; double height; public Person () { } public Person (int age,String name,double height) { this .age = age; this .name = name; this .height = height; } public void eat () { int age = 10 ; System.out.println(age); System.out.println(this .age); System.out.println("我喜欢吃饭" ); } }
1 2 3 4 5 6 7 package com.excepenxi;public class Test { public static void main (String[] args) { Person p = new Person (19 ,"lili" ,160.6 ); p.eat(); } }
this修饰方法
总结:在同一个类中,方法可以互相调用,this.可以省略不写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.excepenxi;public class Person { int age; String name; double height; public Person () { } public Person (int age,String name,double height) { this .age = age; this .name = name; this .height = height; } public void play () { eat(); System.out.println("上网" ); System.out.println("洗澡" ); } public void eat () { System.out.println(age); System.out.println("吃饭" ); } }
this可以修饰构造器
总结:同一个类中的构造器可以相互用this调用
注意:this修饰构造器必须放在第一行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package com.excepenxi;public class Person { int age; String name; double height; public Person () { } public Person (int age,String name,double height) { this (age,name); this .height = height; } public Person (int age,String name) { this (age); this .name = name; } public Person (int age) { this .age = age; } public void play () { eat(); System.out.println("上网" ); System.out.println("洗澡" ); } public void eat () { System.out.println(age); System.out.println("吃饭" ); } }
static的使用
static修饰属性
static修饰属性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.excepenxi;public class Test { int id; static int sid; public static void main (String[] args) { Test t1 = new Test (); t1.id = 10 ; t1.sid = 10 ; Test t2 = new Test (); t2.id = 20 ; t2.sid = 20 ; Test t3 = new Test (); t3.id = 30 ; t3.sid = 30 ; System.out.println(t1.id); System.out.println(t2.id); System.out.println(t3.id); System.out.println(t1.sid); System.out.println(t2.sid); System.out.println(t3.sid); } }
static修饰属性总结
在类加载的时候一起加载入方法区中的静态域中
先于对象存在
访问方式: 对象名.属性名 类名.属性名(推荐)
static修饰属性的应用场景:某些特定的数据想要在内存中共享,只有一块 –》这个情况下,就可以用static修饰的属性
static修饰属性的应用场景 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.excepenxi;public class Student { String name; int age; static String school; public static void main (String[] args) { Student.school = "excepenxi" ; Student s1 = new Student (); s1.name = "张三" ; s1.age = 19 ; Student s2 = new Student (); s2.name = "李四" ; s2.age = 21 ; System.out.println(s2.school); } }
static修饰方法
static修饰方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package com.excepenxi;public class Demo { int id; static int sid; public void a () { System.out.println(id); System.out.println(sid); System.out.println("------a" ); } static public void b () { System.out.println(sid); System.out.println("------b" ); } public static void main (String[] args) { Demo d = new Demo (); d.a(); Demo.b(); d.b(); } }
代码块
类的组成:属性,方法,构造器,代码块,内部类
代码块分类:普通块,构造块,静态块,同步块(多线程)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 package com.excepenxi;public class Test { int a; static int sa; public void a () { System.out.println("-----a" ); { System.out.println("这是普通块" ); System.out.println("----000000" ); int num = 10 ; System.out.println(num); } } public static void b () { System.out.println("------b" ); } { System.out.println("------这是构造块" ); } static { System.out.println("-----这是静态块" ); System.out.println(sa); b(); } public Test () { System.out.println("这是空构造器" ); } public Test (int a) { this .a = a; } public static void main (String[] args) { Test t = new Test (); t.a(); Test t2 = new Test (); t2.a(); } }
总结:代码块执行顺序
最先执行静态块,只在类加载的时候执行一次
一般以后实战写项目:创建工厂,数据库的初始化信息都放入静态块
一般用于执行一些全局性的初始化操作
再执行构造块(不常用)
再执行构造器
再执行方法中的普通块
包、import
包名定义
名字全部小写
中间用.隔开
一般都是公司域名倒着写 : com.jd com.excepenxi
加上模块名字:com.jd.login com.jd.register
不能使用系统中的关键字:nul,con,com1—com9 …..
包声明的位置,一般都在非注释性代码的第一行:package com.excepenxi;
导包问题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.excepenxi;import com.excepenxi.Person; import java.util.Date;public class Test { public static void main (String[] args) { new Person (); new Date (); new java .sql.Date(1000L ); new Demo (); } }
1 2 import com.excepenxi.*; import com.excepenxi.sub.D;
静态导入 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.excepenxi;import static java.lang.Math.*;public class Test { public static void main (String[] args) { System.out.println(random()); System.out.println(PI); System.out.println(round(5.6 )); } public static int round (double a) { return 1000 ; } }
面向对象(中) 封装(Encapsulation)
通过一个属性感受封装 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.excepenxi.test01;public class Girl { private int age; public int duquAge () { return age; } public void shezhiAge (int age) { if (age >= 30 ){ this .age = 18 ; }else { this .age = age; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package com.excepenxi.test01;public class Test { public static void main (String[] args) { Girl g = new Girl (); g.shezhiAge(33 ); System.out.println(g.duquAge()); } }
上面的代码,对于属性age来说,我加了修饰符private,这样外界对它的访问就受到了限制,现在我还想加上其他的限制条件,但是在属性本身上没有办法再加了,所以我们通过定义方法来进行限制条件的添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Girl { private int age; public int getAge () { return age; } public void setAge (int age) { if (age >= 30 ){ this .age = 18 ; }else { this .age = age; } } }
加深练习
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package com.excepenxi.test2;public class Student { private int age; private String name; private String sex; 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 String getSex () { return sex; } public void setSex (String sex) { if ("男" .equals(sex) || "女" .equals(sex) ){ this .sex = sex; }else { this .sex = "男" ; } } public Student () { } public Student (int age,String name,String sex) { this .age = age; this .name = name; this .setSex(sex); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package com.excepenxi.test2;public class Test { public static void main (String[] args) { Student s1 = new Student (); s1.setName("nana" ); s1.setAge(19 ); s1.setSex("女" ); System.out.println(s1.getName()+"---" +s1.getAge()+"----" +s1.getSex()); Student s2 = new Student (18 ,"菲菲" ,"asdfasdfsadf" ); System.out.println(s2.getName()+"---" +s2.getAge()+"----" +s2.getSex()); } }
继承(Inheritance)
类是对对象的抽象
荣耀20 ,小米 红米3,华为 p40 pro —> 类:手机类
继承是对类的抽象:继承就是 is - a 的关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 属性:姓名,年龄,身高,学生编号 方法:吃饭,睡觉,喊叫,学习 属性:姓名,年龄,身高,教师编号 方法:吃饭,睡觉,喊叫,教学 属性:姓名,年龄,身高,员工编号 方法:吃饭,睡觉,喊叫,工作 人类: 属性:姓名,年龄,身高 方法:吃饭,睡觉,喊叫 人类: ---》父类,基类,超类 属性:姓名,年龄,身高 方法:吃饭,睡觉,喊叫 学生类:Student: 属性:学生编号 方法:学习 教师类:Teacher: 属性:教师编号 方法:教学 员工类:Emploee: 属性:员工编号 方法:工作 狗类: 属性:姓名,年龄,身高 方法:吃饭,睡觉,喊叫 上面的案例中: 学生类/教师类/员工类 继承 自 人类 ---》合理 学生类/教师类/员工类 继承 自 狗类 ---》不合理 学生是一个人 教师是一个人 员工是一个人 ---》合理 学生是一个狗 ---》不合理
代码层面的解释:先写父类,再写子类
父类:人类 Person
子类:学生类 Student
Person 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package com.excepenxi.test03;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("可以睡觉。。。" ); } }
Student类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.excepenxi.test03;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类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.excepenxi.test03;public class Test { public static void main (String[] args) { Student s = new Student (); s.setSno(1001 ); s.setAge(18 ); s.setName("菲菲" ); s.setHeight(180.4 ); System.out.println("学生名字为:" +s.getName()+",学生的年纪:" +s.getAge()); s.study(); s.eat(); s.sleep(); } }
父类定义的内容,子类可以直接拿过来用就可以了,不用代码上反复重复定义了
父类private修饰的内容,子类实际上也继承,只是因为封装的特性阻碍了直接调用,但是提供了间接调用的方式,可以间接调用
总结
继承关系
父类/基类/超类
子类/派生类
子类继承父类一定在合理的范围进行继承的 子类 extends 父类
继承的好处
提高了代码的复用性,父类定义的内容,子类可以直接拿过来用就可以了,不用代码上反复重复定义
便于代码的扩展
为了以后多态的使用,是多态的前提
父类private修饰的内容,子类也继承过来了
一个父类可以有多个子类
一个子类只能有一个直接父类,但是可以间接的继承自其它类
继承具有传递性
Student –》继承自 Person —》继承自Object
Object类是所有类的根基父类
所有的类都直接或者间接的继承自Object
继承之权限修饰符
private:在当前类中可以访问
default:缺省修饰符:到同一个包下的其他类都可以访问
protected:最大到不同包下的子类
public:在整个项目中都可以访问
总结: 属性,方法的修饰符有四种:private,缺省,protected,public 类的修饰符有两种:缺省,public
以后写代码,一般属性用private修饰 ;方法用public修饰
继承之方法的重写
重写:发生在子类和父类中,当子类对父类提供的方法不满意的时候,要对父类的方法进行重写
重写有严格的格式要求:子类的方法名字和父类必须一致,参数列表(个数,类型,顺序)也要和父类一致
1 2 3 4 5 6 7 8 public class Person { public void eat () { System.out.println("吃食物" ); } public void sleep () { System.out.println("睡觉" ); } }
1 2 3 4 5 6 7 8 9 public class Student extends Person { public void study () { System.out.println("学习" ); } @override public void eat () { System.out.println("我喜欢吃小龙虾喝啤酒。。" ); } }
1 2 3 4 5 6 7 8 public class Test { public static void main (String[] args) { Student s = new Student (); s.eat(); } }
重载和重写的区别
重载:在同一个类中,当方法名相同,形参列表不同的时候 多个方法构成了重载
重写:在不同的类中,子类对父类提供的方法不满意的时候,要对父类的方法进行重写
super修饰属性和方法
super:指的是:父类的
super可以修饰属性,可以修饰方法;
在子类的方法中,可以通过 super.属性 或 super.方法 的方式,显示的去调用父类提供的属性,方法。在通常情况下,super.可以省略不写
在特殊情况下,当子类和父类的属性重名时,你要想使用父类的属性,必须加上修饰符super.,只能通过super.属性来调用 在特殊情况下,当子类和父类的方法重名时,你要想使用父类的方法,必须加上修饰符super.,只能通过super.方法来调用 在这种情况下,super.就不可以省略不写
super修饰构造器 其实我们平时写的构造器的第一行都有:super() –>作用:调用父类的空构造器,只是我们一般都省略不写 (所有构造器的第一行默认情况下都有super(),但是一旦你的构造器中显示的使用super调用了父类构造器,那么这个super()就不会给你默认分配了。如果构造器中没有显示的调用父类构造器的话,那么第一行都有super(),可以省略不写)
如果构造器中已经显示的调用super父类构造器,那么它的第一行就没有默认分配的super();了
在构造器中,super调用父类构造器和this调用子类构造器只能存在一个,两者不能共存: 因为super修饰构造器要放在第一行,this修饰构造器也要放在第一行
改正二选一即可
以后写代码构造器的生成可以直接使用IDEA提供的快捷键:alt+insert
继承条件下构造方法的执行过程
1 2 3 4 5 6 7 8 9 10 11 12 package com.excepenxi.test10;public class Person { int age; String name; public Person (int age, String name) { super (); this .age = age; this .name = name; } public Person () { } }
1 2 3 4 5 6 7 8 9 public class Student extends Person { double height ; public Student () { } public Student (int age, String name, double height) { super (age, name); this .height = height; } }
1 2 3 4 5 6 public class Test { public static void main (String[] args) { Student s = new Student (19 ,"feifei" ,160.8 ); } }
Object类的toString()方法 所有类都直接或间接的继承自Object类,Object类是所有Java类的根基类 也就意味着所有的Java对象都拥有Object类的属性和方法 如果在类的声明中未使用extends关键字指明其父类,则默认继承Object类
现在,使用toString方法的时候,打印出来的东西 “不好看”,对于其他人来说不友好,可读性不好 我们现在是想知道对象的信息,名字,年龄,身高。。。。。。
出现的问题:子类Student对父类Object提供的toString方法不满意,不满意–》对toString方法进行重写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package com.excepenxi.test01;public class Student { private String name; private int age; private double height; public String getName () { return name; } public void setName (String name) { this .name = name; } public int getAge () { return age; } public void setAge (int age) { this .age = age; } public double getHeight () { return height; } public void setHeight (double height) { this .height = height; } public Student () { } public Student (String name, int age, double height) { this .name = name; this .age = age; this .height = height; } public String toString () { return "这是一个Student对象,这个对象的名字:" +name+",年龄:" +age+",身高:" +height; } }
总结:toString的作用就是对对象进行“自我介绍”,一般子类对父类提供的toString都不满意,都要进行重写
IDEA提供了快捷键
1 2 3 4 5 6 7 8 9 10 11 @Override public String toString () { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", height=" + height + '}' ; }
Object类的equals方法 equals作用:这个方法提供了对对象的内容是否相等 的一个比较方式,对象的内容指的就是属性
父类Object提供的equals就是在比较==地址,没有实际的意义,我们一般不会直接使用父类提供的方法, 而是在子类中对这个方法进行重写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 package com.excepenxi.test02;public class Phone { private String brand; private double price; private int year ; public String getBrand () { return brand; } public void setBrand (String brand) { this .brand = brand; } public double getPrice () { return price; } public void setPrice (double price) { this .price = price; } public int getYear () { return year; } public void setYear (int year) { this .year = year; } @Override public String toString () { return "Phone{" + "brand='" + brand + '\'' + ", price=" + price + ", year=" + year + '}' ; } public Phone () { } public Phone (String brand, double price, int year) { this .brand = brand; this .price = price; this .year = year; } public boolean equals (Object obj) { Phone other = (Phone)obj; if (this .getBrand()==other.getBrand()&&this .getPrice()==other.getPrice()&&this .getYear()==other.getYear()){ return true ; } return false ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.excepenxi.test02;public class Test { public static void main (String[] args) { Phone p1 = new Phone ("华为P40" ,2035.98 ,2020 ); Phone p2 = new Phone ("华为P40" ,2035.98 ,2020 ); System.out.println(p1==p2); boolean flag = p1.equals(p2); System.out.println(flag); } }
利用集成开发工具生成equals方法
类和类之间的关系 小女孩找小男孩
面向对象的思维:找参与者,找女孩类,找男孩类、
体会了什么叫方法的形参,什么叫方法的实参
类和类可以产生关系
将一个类作为另一个类中的方法的形参
将一个类作为另一个类的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class Girl { String name; double weight; Mom m ; public void love (Boy b) { System.out.println("我男朋友的名字是:" +b.name+",我男朋友的年龄是:" +b.age); b.buy(); } public void wechat () { m.say(); } public Girl (String name, double weight) { this .name = name; this .weight = weight; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Boy { int age; String name; public void buy () { System.out.println("跟我谈恋爱,我给你买买买。。。" ); } public Boy (int age, String name) { this .age = age; this .name = name; } }
1 2 3 4 5 6 public class Mom { public void say () { System.out.println("妈妈唠唠叨叨 都是爱,听妈妈的话。。" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Test { public static void main (String[] args) { Boy boy = new Boy (30 ,"鹿晗" ); Girl girl = new Girl ("关晓彤" ,100 ); Boy boy2 = new Boy (35 ,"陈伟霆" ); girl.love(boy2); girl.m = new Mom (); girl.wechat(); } }
多态(Polymorphism)
多态跟属性无关,多态指的是方法的多态,而不是属性的多态
案例:小女孩养动物
1 2 3 4 5 public class Animal { public void shout () { System.out.println("我是小动物,我可以叫。。。" ); } }
1 2 3 4 5 6 7 8 9 public class Cat extends Animal { public void shout () { System.out.println("我是小猫,可以喵喵叫" ); } public void scratch () { System.out.println("我是小猫,我可以挠人" ); } }
1 2 3 4 5 6 7 8 9 public class Dog extends Animal { public void shout () { System.out.println("我是小狗,我可以汪汪叫" ); } public void guard () { System.out.println("我是小狗,我可以看家护院,保护我的小主人。。。" ); } }
1 2 3 4 5 6 7 8 public class Pig extends Animal { public void shout () { System.out.println("我是小猪,我嗯嗯嗯的叫" ); } public void eat () { System.out.println("我是小猪,我爱吃东西。。" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Girl { public void play (Animal an) { an.shout(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Test { public static void main (String[] args) { Girl g = new Girl (); Pig p = new Pig (); Animal an = p; g.play(an); } }
先有父类,再有子类:–》继承;先有子类,再抽取父类 —-》泛化
什么是多态
多态就是多种状态:同一个行为,不同的子类表现出来不同的形态
多态指的就是同一个方法调用,然后由于对象不同会产生不同的行为
多态的好处
为了提高代码的扩展性,符合面向对象的设计原则:开闭原则
开闭原则:指的就是扩展是 开放的,修改是关闭的
注意:多态可以提高扩展性,但是扩展性没有达到最好,以后我们会学习 反射
多态的要素
继承:Cat extends Animal ,Pig extends Animal, Dog extends Animal
重写:子类对父类的方法shout()重写
父类引用指向子类对象
1 2 3 Pig p = new Pig ();Animal an = p;g.play(an);
将上面的代码合为一句话:
Animal an = new Pig();
=左侧:编译期的类型
=右侧:运行期的类型
1 2 3 public void play (Animal an) { an.shout(); }
上面的代码,也是多态的一种非常常见的应用场合:父类当方法的形参,然后传入的是具体的子类的对象,然后调用同一个方法,根据传入的子类的不同展现出来的效果也不同,构成了多态
向下转型、向上转型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Demo { public static void main (String[] args) { Pig p = new Pig (); Animal an = p; an.shout(); Pig pig = (Pig)an ; pig.eat(); pig.age = 10 ; pig.weight = 60.8 ; } }
简单工厂设计模式 不仅可以使用父类做方法的形参,还可以使用父类做方法的返回值类型,真实返回的对象可以是该类的任意一个子类对象。
简单工厂模式的实现,它是解决大量对象创建问题的一个解决方案。将创建和使用分开,工厂负责创建,使用者直接调用即可。
简单工厂模式的基本要求是:
定义一个static方法,通过类名直接调用
返回值类型是父类类型,返回的可以是其任意子类类型
传入一个字符串类型的参数,工厂根据参数创建对应的子类产品
1 2 3 4 5 6 7 8 9 10 public class Test { public static void main (String[] args) { Girl g = new Girl (); Animal an = PetStore.getAnimal("狗" ); g.play(an); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class PetStore { public static Animal getAnimal (String petName) { Animal an = null ; if ("猫" .equals(petName)){ an = new Cat (); } if ("狗" .equals(petName)){ an = new Dog (); } if ("猪" .equals(petName)){ an = new Pig (); } return an; } }
面向对象(下) final修饰符
修饰变量
修饰方法:final修饰方法,那么这个方法不可以被该类的子类重写
修饰类:final修饰类,代表没有子类,该类不可以被继承
一旦一个类被final修饰,那么里面的方法也没有必要用final修饰了(final可以省略不写)
修饰变量 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class Test { public static void main (String[] args) { final int A = 10 ; final Dog d = new Dog (); d.age = 10 ; d.weight = 13.7 ; final Dog d2 = new Dog (); a(d2); b(d2); } public static void a (Dog d) { d = new Dog (); } public static void b (final Dog d) { } }
案例:JDK提供的Math类,看源码发现
抽象类、抽象方法
抽象类和抽象方法的关系:抽象类中可以定义0-n个抽象方法。
抽象类作用:在抽象类中定义抽象方法,目的是为了为子类提供一个通用的模板,子类可以在模板的基础上进行开发,先重写父类的抽象方法,然后可以扩展子类自己的内容。抽象类设计避免了子类设计的随意性,通过抽象类,子类的设计变得更加严格,进行某些程度上的限制,使子类更加的通用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 package com.excepenxi;public abstract class Person { public void eat () { System.out.println("一顿不吃饿得慌" ); } public abstract void say () ; public abstract void sleep () ; } class Student extends Person { @Override public void say () { System.out.println("我是东北人,我喜欢说东北话。。" ); } @Override public void sleep () { System.out.println("东北人喜欢睡炕。。" ); } } class Demo { public static void main (String[] args) { Student s = new Student (); s.sleep(); s.say(); Person p = new Student (); p.say(); p.sleep(); } }
面试题
(1)抽象类不能创建对象,那么抽象类中是否有构造器? 抽象类中一定有构造器。构造器的作用是给子类初始化对象的时候要先super调用父类的构造器。
(2)抽象类是否可以被final修饰? 不能被final修饰,因为抽象类设计的初衷就是给子类继承用的。要是被final修饰了这个抽象类了,就不存在继承了,就没有子类。
接口 接口声明格式 1 2 3 4 [访问修饰符] interface 接口名 [extends 父接口1 ,父接口2 …] { 常量定义; 方法定义; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 package com.excepenxi.test04;public interface TestInterface01 { int NUM = 10 ; void a () ; void b (int num) ; int c (String name) ; } interface TestInterface02 { void e () ; void f () ; } class Student extends Person implements TestInterface01 ,TestInterface02 { @Override public void a () { System.out.println("---1" ); } @Override public void b (int num) { System.out.println("---2" ); } @Override public int c (String name) { return 100 ; } @Override public void e () { System.out.println("---3" ); } @Override public void f () { System.out.println("---4" ); } } class Test { public static void main (String[] args) { TestInterface02 t = new Student (); System.out.println(TestInterface01.NUM); System.out.println(Student.NUM); Student s = new Student (); System.out.println(s.NUM); TestInterface01 t2 = new Student (); System.out.println(t2.NUM); } }
在JDK1.8之前,接口中只有两部分内容
常量:固定修饰符:public static final
抽象方法:固定修饰符:public abstract
在JDK1.8之后,新增非抽象方法
被public default修饰的非抽象方法
注意1:default修饰符必须要加上,否则出错
注意2:实现类中要是想重写接口中的非抽象方法,那么default修饰符必须不能加,否则出错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public interface TestInterface { public static final int NUM= 10 ; public abstract void a () ; public default void b () { System.out.println("-------TestInterface---b()-----" ); } } class Test implements TestInterface { public void c () { b(); TestInterface.super .b(); } @Override public void a () { System.out.println("重写了a方法" ); } @Override public void b () { } }
静态方法
注意1:static不可以省略不写
注意2:静态方法不能重写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public interface TestInterface2 { public static final int NUM = 10 ; public abstract void a () ; public default void b () { System.out.println("-----TestInterface2---b" ); } public static void c () { System.out.println("TestInterface2中的静态方法" ); } } class Demo implements TestInterface2 { @Override public void a () { System.out.println("重写了a方法" ); } public static void c () { System.out.println("Demo中的静态方法" ); } } class A { public static void main (String[] args) { Demo d = new Demo (); d.c(); Demo.c(); TestInterface2.c(); } }
疑问:为什么要在接口中加入非抽象方法???
如果接口中只能定义抽象方法的话,那么我要是修改接口中的内容,那么对实现类的影响太大了,所有实现类都会受到影响。现在在接口中加入非抽象方法,对实现类没有影响,想调用就去调用即可。
内部类 成员内部类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 package com.excepenxi.test07;public class TestOuter { public class D { int age = 20 ; String name; public void method () { int age = 30 ; System.out.println(age); System.out.println(this .age); System.out.println(TestOuter.this .age); } } static class E { public void method () { } } int age = 10 ; public void a () { System.out.println("这是a方法" ); { System.out.println("这是一个普通块" ); class B { } } class A { } D d = new D (); System.out.println(d.name); d.method(); } static { System.out.println("这是静态块" ); } { System.out.println("这是构造块" ); } public TestOuter () { class C { } } public TestOuter (int age) { this .age = age; } } class Demo { public static void main (String[] args) { TestOuter to = new TestOuter (); to.a(); TestOuter.E e = new TestOuter .E(); TestOuter t = new TestOuter (); TestOuter.D d = t.new D (); } }
局部内部类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package com.excepenxi.test08;public class TestOuter { public void method () { final int num = 10 ; class A { public void a () { System.out.println(num); } } } public Comparable method2 () { class B implements Comparable { @Override public int compareTo (Object o) { return 100 ; } } return new B (); } public Comparable method3 () { return new Comparable (){ @Override public int compareTo (Object o) { return 200 ; } }; } public void teat () { Comparable com = new Comparable (){ @Override public int compareTo (Object o) { return 200 ; } }; System.out.println(com.compareTo("abc" )); } }
面向对象项目
匹萨父类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package com.excepenxi.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; } }
培根匹萨 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.excepenxi.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; } @Override public String showPizza () { return super .showPizza()+"\n培根的克数是:" +weight+"克" ; } }
水果匹萨 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.excepenxi.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; } @Override public String showPizza () { return super .showPizza()+"\n你要加入的水果:" +burdening; } }
测试类 1 2 3 4 5 6 7 8 9 10 11 12 public class Test { 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 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package com.excepenxi.test01;import java.util.Scanner;public class PizzaStore { public static Pizza getPizza (int choice) { Scanner sc = new Scanner (System.in); Pizza p = null ; switch (choice){ case 1 : { 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); 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); p = fp; } break ; } return p; } }
异常(Exception) 在程序的运行过程中,发生了不正常的现象,阻止了程序的运行,我们称之为发生异常
1 2 3 4 5 6 7 8 9 10 11 12 public class Test { public static void main (String[] args) { Scanner sc = new Scanner (System.in); System.out.print("请录入第一个数:" ); int num1 = sc.nextInt(); System.out.print("请录入第二个数:" ); int num2 = sc.nextInt(); System.out.println("商:" +num1/num2); } }
通过if-else解决异常 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.excepenxi.test01;import java.util.Scanner;public class Test { public static void main (String[] args) { Scanner sc = new Scanner (System.in); System.out.print("请录入第一个数:" ); if (sc.hasNextInt()){ int num1 = sc.nextInt(); System.out.print("请录入第二个数:" ); if (sc.hasNextInt()){ int num2 = sc.nextInt(); if (num2 == 0 ){ System.out.println("对不起,除数不能为0" ); }else { System.out.println("商:" +num1/num2); } }else { System.out.println("对不起,你录入的不是int类型的数据!" ); } }else { System.out.println("对不起,你录入的不是int类型的数据!" ); } } }
用if-else堵漏洞的缺点
代码臃肿,业务代码和处理异常的代码混在一起
可读性差
程序员需要花费大量的经历来维护这个漏洞
程序员很难堵住所有的漏洞
try-catch捕获异常 基于if-else处理异常缺点太多,所以java中专门出了一个异常处理机制:”异常三连” try-catch-finally
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Test2 { public static void main (String[] args) { try { Scanner sc = new Scanner (System.in); System.out.print("请录入第一个数:" ); int num1 = sc.nextInt(); System.out.print("请录入第二个数:" ); int num2 = sc.nextInt(); System.out.println("商:" +num1/num2); }catch (Exception ex){ System.out.println("对不起,程序出现异常!" ); } System.out.println("----谢谢你使用计算器111" ); System.out.println("----谢谢你使用计算器222" ); System.out.println("----谢谢你使用计算器333" ); } }
原理: 把可能出现异常的代码放入try代码块中,然后将异常封装为对象,被catch后面的()中的那个异常对象接收,接收以后:执行catch后面的{}里面的代码,然后try-catch后面的代码,该怎么执行就怎么执行。
详细说一下: (1)try中没有异常,catch中代码不执行 (2)try中有异常,catch进行捕获: 如果catch中异常类型和你出的异常类型匹配的话:走catch中的代码–》进行捕获 如果catch中异常类型和你出的异常类型不匹配的话:不走catch中的代码–》没有捕获成功,程序相当于遇到异常了,中断了,后续代码不执行
注意:
(1)try中如果出现异常,然后用catch捕获成功的话,那么try中后续的代码是不会执行的 (2)如果catch捕获异常成功,那么try-catch后面的代码该执行还是执行没有影响
catch中如何处理异常 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package com.excepenxi.test01;import java.util.Scanner;public class Test3 { public static void main (String[] args) { try { Scanner sc = new Scanner (System.in); System.out.print("请录入第一个数:" ); int num1 = sc.nextInt(); System.out.print("请录入第二个数:" ); int num2 = sc.nextInt(); System.out.println("商:" +num1/num2); }catch (Exception ex){ ex.printStackTrace(); } System.out.println("----谢谢你使用计算器111" ); } }
try-catch-finally
在什么情况下,try-catch后面的代码不执行?
throw抛出异常的情况
catch中没有正常的进行异常捕获
在try中遇到return
怎么样才可以将 try-catch后面的代码 必须执行?
只要将必须执行的代码放入finally中,那么这个代码无论如何一定执行
return和finally执行顺序?
什么代码会放在finally中呢?
关闭数据库资源,关闭IO流资源,关闭socket资源
有一句话代码很厉害,它可以让finally中代码不执行!
System.exit(0);
//终止当前的虚拟机执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.excepenxi.test01;import java.util.Scanner;public class Test3 { public static void main (String[] args) { try { Scanner sc = new Scanner (System.in); System.out.print("请录入第一个数:" ); int num1 = sc.nextInt(); System.out.print("请录入第二个数:" ); int num2 = sc.nextInt(); System.out.println("商:" +num1/num2); System.exit(0 ); return ; }catch (ArithmeticException ex){ }finally { System.out.println("----谢谢你使用计算器111" ); } } }
多重catch
try中出现异常以后,将异常类型跟catch后面的类型依次比较,按照代码的顺序进行比对,执行第一个与异常类型匹配的catch语句
一旦执行其中一条catch语句之后,后面的catch语句就会被忽略了!
在安排catch语句的顺序的时候,一般会将特殊异常放在前面(并列),一般化的异常放在后面
先写子类异常,再写父类异常
在JDK1.7以后,异常新处理方式:可以并列用|
符号连接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package com.excepenxi.test01;import java.util.InputMismatchException;import java.util.Scanner;public class Test4 { public static void main (String[] args) { Integer try { Scanner sc = new Scanner (System.in); System.out.print("请录入第一个数:" ); int num1 = sc.nextInt(); System.out.print("请录入第二个数:" ); int num2 = sc.nextInt(); System.out.println("商:" +num1/num2); }catch (ArithmeticException ex){ System.out.println("对不起,除数不可以为0" ); }catch (InputMismatchException ex){ System.out.println("对不起,你录入的数据不是int类型的数据" ); }catch (Exception ex){ System.out.println("对不起,你的程序出现异常" ); }finally { System.out.println("----谢谢你使用计算器111" ); } } }
异常的分类
注意:程序中语法错误,逻辑错误 都不属于上面的Error,Exception
运行时异常 1 2 3 4 5 6 7 8 9 10 11 public class Test5 { public static void main (String[] args) { int [] arr = {1 ,2 ,3 }; System.out.println(arr.length); System.out.println(arr[10 ]); } }
try-catch嵌套try-catch 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Test6 { public static void main (String[] args) { try { try { Class.forName("com.excepenxi.test01.Test" ).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
多重catch 1 2 3 4 5 6 7 8 9 10 11 public class Test6 { public static void main (String[] args) { try { Class.forName("com.excepenxi.test01.Test" ).newInstance(); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { e.printStackTrace(); } } }
throws 1 2 3 4 5 6 7 public class Test6 { public static void main (String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException { Class.forName("com.excepenxi.test01.Test" ).newInstance(); } }
throw和throws的区别 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package com.excepenxi.test01;import java.util.Scanner;public class Test7 { public static void main (String[] args) throws Exception { devide(); } public static void devide () throws Exception { Scanner sc = new Scanner (System.in); System.out.print("请录入第一个数:" ); int num1 = sc.nextInt(); System.out.print("请录入第二个数:" ); int num2 = sc.nextInt(); if (num2 == 0 ){ throw new Exception (); }else { System.out.println("商:" +num1/num2); } } }
(1)位置不同: throw:方法内部 throws: 方法的签名处,方法的声明处
(2)内容不同: throw+异常对象(检查异常,运行时异常) throws+异常的类型(可以多个类型,用逗号,
拼接)
(3)作用不同: throw:异常出现的源头,制造异常。 throws:在方法的声明处,告诉方法的调用者,这个方法中可能会出现我声明的这些异常。然后调用者对这个异常进行处理:要么自己处理要么再继续向外抛出异常
练习
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 package com.excepenxi.test02;public class Student { private String name; private int age; private String sex; public String getName () { return name; } public void setName (String name) { this .name = name; } public int getAge () { return age; } public void setAge (int age) { this .age = age; } public String getSex () { return sex; } public void setSex (String sex) throws Exception { if (sex.equals("男" )||sex.equals("女" )){ this .sex = sex; }else { throw new Exception (); } } @Override public String toString () { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + '}' ; } public Student () { } public Student (String name, int age, String sex) { this .name = name; this .age = age; try { this .setSex(sex); } catch (Exception e) { e.printStackTrace(); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.excepenxi.test02;public class Test { public static void main (String[] args) { Student s2 = new Student ("娜娜" ,21 ,"asdfasdfasdf" ); System.out.println(s2); } }
重载和重写的异常
重载 1 2 3 4 5 6 7 public class Demo { public void a () throws Exception{ } public void a (int age) throws ArithmeticException{ } }
自定义异常 自定义的异常可以继承:运行时异常
1 2 3 4 5 6 7 8 public class MyException extends RuntimeException { static final long serialVersionUID = -70348971907L ; public MyException () { } public MyException (String msg) { super (msg); } }
也可以继承检查异常
1 2 3 4 5 6 7 8 public class MyException extends Exception { static final long serialVersionUID = -70348971907L ; public MyException () { } public MyException (String msg) { super (msg); } }
如果继承的是运行时异常,那么在使用的时候无需额外处理 如果继承的是检查异常,那么使用的时候需要try-catch捕获或者throws向上抛