1.继承
1.1继承定义
继承是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及 追加属性和方法(子类可以使用父类中非私有的成员。)
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
eg:我有动物类,猫类,狗类(首先这些符合is a继承关系)猫类和狗类有相同特征:名字,年龄,要吃食物等。然后我们就可以将这相同特征部分抽象到动物类里面
下面是实现代码: Animal实现了抽象的相同特征,以便子类调用
/**
* 父类
*/
public class Animal {
//成员变量
String name; //动物名字
int age; //动物年龄
//eat方法 成员方法
public void eat(String food){
System.out.println("一只"+this.age+"岁的"+this.name+"要吃"+food);
}
//构造方法
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
//构造方法 空构造,建议加上
public Animal() {
}
//get set方法
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;
}
}
俩个子类,Cat,Dog子类的name age相同属性以及eat相同方法共同组成的相同特征在父类实现
/**
* 子类
**/
public class Cat extends Animal{
public void eat(String name,int age,String food){
Animal animal = new Animal(name,age);
animal.eat(food);
}
}
/**
* 子类
**/
public class Dog extends Animal{
public void eat(String name,int age,String food){
Animal animal = new Animal(name,age);
animal.eat(food);
}
}
测试类 创建对象,调用eat方法就能得到下面的结果
/**
测试方法
**/
public class Text {
public static void main(String[] args) {
Cat cat = new Cat();//Cat对象引用
//调用eat方法
cat.eat("Tom猫",2,"鱼");
System.out.println("----------------------");
Dog dog = new Dog();//Dog对象引用
//调用eat方法
dog.eat("旺财",5,"chouchou");
}
}
一只2岁的Tom猫要吃鱼
----------------------
一只5岁的旺财要吃chouchou
看完大致用法,下面就里面细节进行介绍
1.2继承格式
public class 子类名 externs 父类名{}
externs可以理解为扩展,即父类是子类的扩展,子类就可以调用父类的方法
1.3继承的好处与弊端
好处:
提高代码的复用性(创建一个父类存放多个子类相同的部分)
提高代码的维护性(由于相同的部分移至到一个类里,方便修改)
弊端:
继承实现代码的复用,增加了子类与父类之间的耦合性,使得更改
父类,子类一定会跟着变化 ------引用黑马程序员
1.4继承使用原则
要满足is a关系,即A是B的一部分或B是A的一部分时可以考虑使用继承
1.5继承中访问变量的特点
子类方法中访问一个变量:
首先在子类局部范围找
其次在子类成员范围找
最后再父类成员范围找(包括父类的父类)
如果都没有就报错
public class Jicheng{
public String weight = "50kg";//父类的父类找的变量
}
class Fu extends Jicheng{
public String height = "170cm";//父类成员找的变量
}
class Zi extends Fu {
int age = 18;//子类成员范围找的变量
public void show(){
String color = "yellow";//子类局部范围找的变量
System.out.println(height);
System.out.println(weight);
System.out.println(age);
System.out.println(color);
}
/**
* 内部测试类
* @param args
*/
public static void main(String[] args) {
Zi zi = new Zi();
zi.show();
}
}
1.6继承中构造方法的访问特点
子类中的构造方法都会默认在前面加一个supper(); 然后就会调用到父类的构造方法;要是想解除,则要在子类构造方法中定义一个显示的有参构造;这个子类就会不调用父类无参构造而调用有参构造; 从这里不难看出,在自己添加有参构造时,最好在加上无参构造;
/**
* Zi
* @author 祥瑞
*/
public class Zi extends Fu{
int age;
public Zi(){
System.out.println("Zi类无参构造");
}
public Zi(int age) {
this.age = age;
System.out.println("Zi类有参构造");
}
}
/**
* Fu
* @author 祥瑞
*/
public class Fu {
int age;
public Fu(){
System.out.println("Fu类无参构造");
}
public Fu(int age) {
this.age = age;
System.out.println("Fu类有参构造");
}
}
public class Demo {
public static void main(String[] args) {
Zi zi = new Zi();
Zi zi2 = new Zi(18);
}
}
运行结果(原因如上)
Fu类无参构造
Zi类无参构造
Fu类无参构造
Zi类有参构造
1.7继承中成员方法访问的特点
和成员变量访问特点差不多,访问成员方法时,也是先从子类里找成员方法,没有再去父类找,再没有的话就报错
1.8suppr内存图
/**
* Zi
* @author 祥瑞
*/
public class Zi extends Fu{
int age = 30;
public void method(){
int age = 20;
System.out.println("Zi类ziMethod方法");
System.out.println(age);
System.out.println(this.age);
System.out.println(super.age);
}
}
/**
* Fu
* @author 祥瑞
*/
public class Fu {
int age = 40;
public void show(){
System.out.println("Fu类show方法");
}
}
public class Demo {
public static void main(String[] args) {
Zi zi = new Zi();
zi.method();
zi.show();
}
}
运行结果:
Zi类ziMethod方法
20
30
40
Fu类show方法
下面详细介绍机器堆栈的运行情况
运行到public static void main(String[] args)这句时情况如下,main方法进入栈中
运行到 Zi zi = new Zi(); 时,先把zi动作加载到main方法里面,然后是在堆中创建一个内存,情况图如下:
但是子类构造方法会默认访问父类的构造方法,然后就进入到父类中,存放了父类的age,如图:
运行到 zi.method(); 时,method方法会进入栈内存中,如图
此时输出的
age = 20
this.age = 30 直接找this的地址
supper.age = 40 先找Zi的地址,然后找到supper空间
运行到 zi.show(); 时,就会在栈中弹出method方法,然后show方法进入栈内存,由于Zi里面没有,然后就会从Fu里找,最后存到栈中的是Fu的show方法,如图所示
最后依次弹出show方法和main方法。展示结束
1.9方法重写及其注意事项
优点:方法重写可以既包含父类的内容,还可以添加子类自己独特的内容;
注意事项:子类重写的方法的访问权限要高于父类,父类的私有方法不可以被重写,可以用@Override注释进行验证。
1.10继承注意事项
java支持单继承,可以多层继承;
即一个类只可以继承一个类,但父类还可以继承别的类;
拓展:java接口可以实现多实现在以后碰到选择继承还是实现时,一般选择实现接口,因为实现可以多实现,没有单继承这方面的限制。
2. 修饰符
2.1 package(了解)
1、包的概念
包就是文件夹,用来管理类文件的
2、包的定义格式
package 包名; (多级包用.分开) 例如:package com.heima.demo;
3、带包编译&带包运行
带包编译:javac –d . 类名.java 例如:javac -d . com.heima.demo.HelloWorld.java
带包运行:java 包名+类名 例如:java com.heima.demo.HelloWorld
2.2 import(理解)
导包的意义
使用不同包下的类时,使用的时候要写类的全路径,写起来太麻烦了
为了简化带包的操作,Java就提供了导包的功能
导包的格式
格式:import 包名; 范例:import java.util.Scanner;
示例代码(没有使用导包,创建的Scanner对象)
package com.heima;
public class Demo {
public static void main(String[] args) {
// 1. 没有导包,创建Scnaner对象
java.util.Scanner sc = new java.util.Scanner(System.in);
}
}
示例代码(使用导包后,创建的Scanner对象)
package com.heima;
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
// 1. 没有导包,创建Scnaner对象
Scanner sc = new Scanner(System.in);
}
}
2.3 权限修饰符(理解)
2.4 final(应用)
- final关键字的作用
final代表最终的意思,可以修饰成员方法,成员变量,类
- final修饰类、方法、变量的效果
final修饰类:该类不能被继承(不能有子类,但是可以有父类)
final修饰方法:该方法不能被重写
final修饰变量:表明该变量是一个常量,不能再次赋值
2.5 final修饰局部变量(理解)
- final修饰基本数据类型变量
final 修饰指的是基本类型的数据值不能发生改变
- final修饰引用数据类型变量
final 修饰指的是引用类型的地址值不能发生改变,但是地址里面的内容是可以发生改变的
举例:
public static void main(String[] args){
final Student s = new Student(23);
s = new Student(24); // 错误
s.setAge(24); // 正确
}
2.6 static(应用)
- static的概念
static关键字是静态的意思,可以修饰【成员方法】,【成员变量】
- static修饰的特点
- 被类的所有对象共享,这也是我们判断是否使用静态关键字的条件
- 可以通过类名调用当然,也可以通过对象名调用【推荐使用类名调用】
- 示例代码:
class Student {
public String name; //姓名
public int age; //年龄
public static String university; //学校 共享数据!所以设计为静态!
public void show() {
System.out.println(name + "," + age + "," + university);
}
}
public class StaticDemo {
public static void main(String[] args) {
// 为对象的共享数据赋值
Student.university = "传智大学";
Student s1 = new Student();
s1.name = "林青霞";
s1.age = 30;
s1.show();
Student s2 = new Student();
s2.name = "风清扬";
s2.age = 33;
s2.show();
}
}
2.7 static访问特点(掌握)
-static的访问特点
非静态的成员方法
能访问静态的成员变量
能访问非静态的成员变量
能访问静态的成员方法
能访问非静态的成员方法
静态的成员方法
能访问静态的成员变量
能访问静态的成员方法
总结成一句话就是
静态成员方法只能访问静态成员
3.多态
多态概述
同一个对象在不同时刻表现的不同状态
多态的前提和体现
1.有继承、实现关系
2.有方法重写
有父类引用指向子类对象
eg:Animal cat = new Cat();
Cat cat = new Cat();
案例展示(有关运行结果的看3.2)
public class Animal {
public void eat(){
int eag = 40;
System.out.println("吃东西");
}
}
public class Cat extends Animal{
int age = 20;
int hight = 5;
public void play(){
System.out.println("猫玩线圈");
}
@Override
public void eat() {
System.out.println("猫吃老鼠");
}
}
public class Demo {
public static void main(String[] args) {
//父类引用指向子类对象
Animal animal = new Cat();
//System.out.println(a.wight); 报错
System.out.println(animal.age);
animal.eat();
//animal.play(); 报错
//正常
Animal a = new Animal();
a.eat();
//a.play(); 报错
System.out.println(a.age);
//System.out.println(a.wight); 报错
Cat cat = new Cat();
cat.eat();
cat.play();
System.out.println(cat.age);
System.out.println(cat.wight);
}
}
运行结果
40
猫吃老鼠
吃东西
40
猫吃老鼠
猫玩线圈
20
5
3.2多态中成员变量的访问特点
- 成员变量:编译看左边,执行看左边(继承子类扩展了)
- 成员方法:编译看左边,执行看右边
之所以这样是方法有重写,而变量没有
3.3多态的好处和弊端
好处:提高程序的扩展性 可以使用父类作为参数,直接传子类对象调用方法就能调用子类的方法
弊端:不能调用子类特有的方法
3.4多态的转型
向上转型:从下到上
有父类引用指向子类对象;Animal a = new Cat();
向下转型:从上到下
父类引用转为子类对象
Animal a = new Cat();
Cat c = (Cat)a;
注意强转类型时,双方要有一定的关系,例如:Cat类型不能强制转化成Dog类型
4.抽象类
4.1抽象类概述
java中,如果一个方法没有方法体,它则是一个抽象方法,具有抽象方法的类时抽象类;
格式:public abstract void 方法名();此时类必须定义为抽象类;
4.2抽象类的特点
1.抽象类 public abstract class 类名{} 抽象方法 public abstract void 方法名();
2.有抽象方法必须要定义为抽象类,抽象类不一定要有抽象方法;
3.抽象类不能直接实例化,但可以参照多态的方式,通过子类对象实例化,这叫抽象多态
4.抽象类的子类要么重写抽象方法,要么定义为抽象类;
4.3抽象类的成员特点
成员变量:可以是变量,也可以是常量
成员方法:可以是抽象方法,也可以是非抽象方法
构造方法:用于子类访问父类数据的初始化,使其通过子类完成实例化
猫狗类(抽象类版)
public abstract class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
/**
* 抽象方法
* eat()
*/
public abstract void eat();
}
public class Cat extends Animal{
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃骨头");
}
public Dog() {
}
public Dog(String name, int age) {
super(name, age);
}
}
public class AnimalDemo {
public static void main(String[] args) {
Animal a = new Cat("加菲猫",5);
a.eat();
Animal b = new Dog("哈士奇",8);
b.eat();
}
}
运行结果:
猫吃鱼
狗吃骨头
5.接口
5.1接口概述
接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用
java中的接口更多的体现在对行为的抽象
5.2接口特点
1.用interface修饰
格式:public interface 接口名{}
2.类实现接口用implements
格式:public class 类名 implements 接口名{}
3.接口不能直接实例化,但可以参照多态的方式,通过实现类对象实例化,这叫接口多态
多态包含 具体类多态,抽象多态,接口多态
完全版多态前提;具有继承或者实现关系;有方法重写;有父(类/接口)引用指向(子/实现)类对象
4.接口实现类:要么重写所有接口抽象方法,要么是抽象类
5.3接口的成员特点
1.接口中的成员变量只能是常量,因为有默认修饰符public static final
2.构造方法:没有构造方法,但实现类里有super,这是因为每个类都直接或间接继承object类
3.成员方法:只能是抽象方法,默认修饰符public abstract
5.4猫狗类(接口版)
public interface Jumpping {
/**
* jump抽象方法
* jump
*/
public abstract void jump();
}
public abstract class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
/**
* 抽象方法
* eat()
*/
public abstract void eat();
}
public class Cat extends Animal implements Jumpping{
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void jump() {
System.out.println("猫在跳高");
}
}
public class Dog extends Animal implements Jumpping{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
public Dog() {
}
public Dog(String name, int age) {
super(name, age);
}
@Override
public void jump() {
System.out.println("狗在跳高");
}
}
public class AnimalDemo {
public static void main(String[] args) {
Jumpping j1 = new Cat();
j1.jump();
Animal a = new Cat("加菲猫",5);
a.eat();
//强转
((Cat)a).jump();
Jumpping j = new Dog("哈士奇",5);
j.jump();
Animal b = new Dog("哈士奇",8);
b.eat();
System.out.println("最好直接用具体类,因为接口,超类都在里面");
Cat s = new Cat();
s.eat();
s.jump();
}
}
运行结果
猫在跳高
猫吃鱼
猫在跳高
狗在跳高
狗吃骨头
最好直接用具体类,因为接口,超类都在里面
猫吃鱼
猫在跳高
5.5类和接口的关系
类和类只能单继承,类和接口可以单实现也可以·多实现;
接口和接口可以单继承也可以多继承
5.6抽象类和接口的区别
语法上:抽象类:变量,常量,抽象方法,非抽象方法
接口:常量,抽象方法
设计上:抽象类:对类抽象,包括行为和属性
接口:对行为抽象,主要是行为
5.7运动员教练实例
抽象Person类
public abstract class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
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;
}
/**
* 抽象方法
* eat()
*/
public abstract void eat();
}
抽象Coach类
public abstract class Coach extends Person{
public Coach(String name, int age) {
super(name, age);
}
public Coach() {
}
/**
* teach 抽象方法
*/
public abstract void teach();
}
抽象Student类
public abstract class Student extends Person{
public Student(String name, int age) {
super(name, age);
}
public Student() {
}
/**
* study() 抽象方法
*/
public abstract void study();
}
接口SpeakEnglish
public interface SpeakEnglish {
/**
* speakEnglish 接口方法
*/
void speakEnglish();
}
BasketballCoach 篮球教练类
public class BasketballCoach extends Coach{
@Override
public String toString() {
return super.getName()+","+super.getAge();
}
public BasketballCoach(String name, int age) {
super(name, age);
}
public BasketballCoach() {
super();
}
@Override
public void teach() {
System.out.println("篮球教练教学生打篮球");
}
@Override
public void eat() {
System.out.println("篮球教练吃猪肉,喝牛奶");
}
}
PingPangCoach 乒乓球教练类
public class PingPangCoach extends Coach implements SpeakEnglish{
public PingPangCoach(String name, int age) {
super(name, age);
}
public PingPangCoach() {
super();
}
@Override
public void teach() {
System.out.println("平平教练教学生打乒乓球");
}
@Override
public void eat() {
System.out.println("乒乓教练吃鸡肉,喝可乐");
}
@Override
public void speakEnglish() {
System.out.println("乒乓教练教学生讲英语");
}
}
BasketballStudent 篮球学生类
public class BasketballStudent extends Student{
@Override
public String toString() {
return super.getName()+","+super.getAge();
}
public BasketballStudent(String name, int age) {
super(name, age);
}
public BasketballStudent() {
super();
}
@Override
public void study() {
System.out.println("篮球学生学打篮球");
}
@Override
public void eat() {
System.out.println("篮球学生吃牛肉,喝小米粥");
}
}
PingPangStudent 乒乓球学生类
public class PingPangStudent extends Student implements SpeakEnglish{
public PingPangStudent(String name, int age) {
super(name, age);
}
public PingPangStudent() {
super();
}
@Override
public void speakEnglish() {
System.out.println("乒乓球学生学说英语");
}
@Override
public void study() {
System.out.println("乒乓球学生学打乒乓");
}
@Override
public void eat() {
System.out.println("乒乓球学生吃羊肉,喝排骨汤");
}
}
Demo测试类
public class Demo {
public static void main(String[] args) {
//创建篮球教练对象,调用方法
BasketballCoach basketballCoach = new BasketballCoach("王哲",18);
System.out.println("basketballCoach = " + basketballCoach.toString());
basketballCoach.eat();
basketballCoach.teach();
//创建篮球学生对象,调用方法
BasketballStudent basketballStudent = new BasketballStudent("曲浩然",15);
System.out.println("basketballStudent = " + basketballStudent.toString());
basketballStudent.eat();
basketballStudent.study();
//创建乒乓球教练对象,调用方法
PingPangCoach pingPangCoach = new PingPangCoach("葛盼溪",19);
System.out.println("pingPangCoach = " + pingPangCoach.toString());
pingPangCoach.eat();
pingPangCoach.teach();
pingPangCoach.speakEnglish();
//创建乒乓球学生对象,调用方法
PingPangStudent pingPangStudent = new PingPangStudent("朱勋鑫",16);
System.out.println("pingPangStudent = " + pingPangStudent.toString());
pingPangStudent.eat();
pingPangStudent.study();
pingPangStudent.speakEnglish();
}
}
运行结果
basketballCoach = 王哲,18
篮球教练吃猪肉,喝牛奶
篮球教练教学生打篮球
basketballStudent = 曲浩然,15
篮球学生吃牛肉,喝小米粥
篮球学生学打篮球
pingPangCoach = nenu.com.anli05.PingPangCoach@1b6d3586
乒乓教练吃鸡肉,喝可乐
平平教练教学生打乒乓球
乒乓教练教学生讲英语
pingPangStudent = nenu.com.anli05.PingPangStudent@4554617c
乒乓球学生吃羊肉,喝排骨汤
乒乓球学生学打乒乓
乒乓球学生学说英语
6.内部类
6.1参数传递
类名,抽象类,接口作为形参和返回值
作为方法的形参,其实要的是该类的对象,传递的是对象的地址
普通类
class Father{
public void eat(){
System.out.println("Father的eat方法");
}
}
class Son{
public Father eat(Father f){ //Father f = new Father();
System.out.println("Son的eat方法");
return f;
}
}
public class Demo {
public static void main(String[] args) {
Father father = new Father();
Son son = new Son();
son.eat(father); //将new的对象传进去
father.eat();
}
}
运行结果
Son的eat方法
Father的eat方法
抽象类
abstract class Father{
public void eat(){
System.out.println("Father的eat方法");
}
}
class Son extends Father{
public Father eat(Father f){ //Father f = new Son();
System.out.println("Son的eat方法");
return f;
}
}
public class Demo {
public static void main(String[] args) {
Father father = new Son();
Son son = new Son();
son.eat(father); //将new的子类对象传进去
father.eat();
}
}
区别在于这里new的是子类的对象,运行结果
Son的eat方法
Father的eat方法
接口
interface Father{
public abstract void eat(Father f);
}
class Son implements Father{
@Override
public void eat(Father f) { //Father f = new Son();
System.out.println("Son 的 eat");
}
public Father eat(){
Father f = new Son();
return f;
}
}
public class Demo {
public static void main(String[] args) {
Father father = new Son();
Son son = new Son();
son.eat(father); //将new的子类对象传进去
}
}
运行结果
Son 的 eat
6.2内部类种类
格式
/*
格式:
class 外部类名{
修饰符 class 内部类名{
}
}
*/
class Outer {
public class Inner {
}
}
成员内部类位置:可以用访问修饰符,成员变量位置,外部类调用内部类方法要创建对象
局部内部类位置:不可以用访问修饰符,方法体内,外部类要调用内部类方法要也要创建对象,详情见下面案例
class Outer{
private int age = 5;
public void method(){
//可以调用私密成员
System.out.println(age);
//想要用内部类的方法要先创建对象
Inter inter = new Inter();
inter.eat();
}
/**
* 成员内部类
*/
private class Inter{
private void eat(){
System.out.println("eat方法");
}
}
}
public class Text {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
5
eat方法
class Outer{
private int age = 5;
public void method(){
//可以调用私密成员
System.out.println(age);
//想要用内部类的方法要先创建对象
Inter inter = new Inter();
inter.eat();
}
/**
* 成员内部类
*/
private class Inter{
private void eat(){
System.out.println("eat方法");
}
}
}
public class Text {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
5
eat方法
匿名内部类就是不给内部类起名字,且只使用一次,后续不再使用建议使用
在使用时用于简化开发,大多数传递对象的地方,且只使用一次时,可以使用new 类名/接口名来“创建对象”,简化了代码
格式:类名 a = new 类名(){方法体};
可以继续调用方法体里的内容 a调用即可,案例
public class Demo01 {
public static void main(String[] args) {
//基于类的匿名内部类
AA a = new AA(){};
a.method();
//基于接口的匿名内部类
BB b = new BB() {
@Override
public void eat() {
System.out.println("匿名内部类eat");
}
};
b.eat();
}
}
class AA{
public void method(){
System.out.println("method方法");
}
}
interface BB{
public abstract void eat();
}
运行结果
method方法
匿名内部类eat
7.异常
7.1异常体系
如图
Throwable 所有异常的超类
Error 严重错误,一般是计算机硬件问题,不需要处理
Exception 需要处理
RuntimeException 可通过编译,需要回来修改代码
非RuntimeException 不可通过编译,编译时就需要处理
7.2 java异常处理方式
默认方式
jvm会将异常名称,异常原因,异常位置进行输出,程序停止
手动处理自己利用try{}catch{}final{}
程序会先看try里面是否有异常,有就会交给catch,然后输出里面自己手动设置的内容,然后正常运行下面的内容,fanai是无论有没有异常,都一定会执行的操作。
public class ExceptionDemo {
int[] arr = {1,2,3};
public void method(){
System.out.println(arr[3]);
}
public void method1(){
try{
System.out.println(arr[3]);
}catch (Exception e){
System.out.println("你的数组下标越界");
e.printStackTrace();
}
}
public static void main(String[] args) {
ExceptionDemo exceptionDemo = new ExceptionDemo();
exceptionDemo.method1();
//exceptionDemo.method();
}
}
你的数组下标越界
java.lang.ArrayIndexOutOfBoundsException: 3
at nenu.com.text09.ExceptionDemo.method1(ExceptionDemo.java:20)
at nenu.com.text09.ExceptionDemo.main(ExceptionDemo.java:29)
7.3 Throwable成员方法
方法名 | 说明 |
---|---|
public String getMessage() | 返回此 throwable 的详细消息字符串 |
public String toString() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
7.4 编译时异常和运行时异常的区别
-
编译时异常
- 都是Exception类及其子类
- 必须显示处理,否则程序就会发生错误,无法通过编译
-
运行时异常
- 都是RuntimeException类及其子类
- 无需显示处理,也可以和编译时异常一样处理
7.5 throws方式处理异常
- 定义格式
public class ThrowDemo {
public void 方法名() throws 异常类{}
}
- 案例
public class ThrowDemo {
int[] arr = {1,2,3};
public void method() throws ArrayIndexOutOfBoundsException{
System.out.println(arr[3]);
}
public static void main(String[] args) {
ThrowDemo t = new ThrowDemo();
t.method();
}
}
运行结果
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at nenu.com.text09.ThrowDemo.method(ThrowDemo.java:15)
at nenu.com.text09.ThrowDemo.main(ThrowDemo.java:20)
总结:1)throws抛出异常,这种方式和默认方式一样,程序还是会死亡
2)谁出现异常监视谁try{}catch{},这钟方式程序不会死亡,但是上层调用者不知道底层执行情况
3)那么如果出现异常层层上抛,有上层集中处理,这样程序既不会死亡,也知道了底层的执行情况,是较好的做法
7.6 throws和throw的区别
throws | throw |
---|---|
用在方法声明后面,跟的是异常类名 | 用在方法体内,跟的是异常对象名 |
表示抛出异常,由该方法的调用者处理 | 表示抛出异常,由方法体内的语句处理 |
表示出现异常可能性,但不一定发生 | 执行throw一定出现了异常 |
7.7 自定义异常
案例展示
- 自定义异常类
要继承Exception,然后写一些方法
public class ScoreException extends Exception{
public ScoreException() {
}
public ScoreException(String message) {
super(message);
}
}
- Teacher类`
public class Teacher {
public void scoreCheck(int score) throws ScoreException{
if(score<0||score>100){
throw new ScoreException("分数范围错误,应该在0~100之间");
}else {
//输出正确
System.out.println("");
}
}
}
- Demo类
public class Demo {
public static void main(String[] args) throws ScoreException {
Scanner sc = new Scanner(System.in);
System.out.println("请输入学生分数:");
int score = sc.nextInt();
Teacher t = new Teacher();
t.scoreCheck(score);
// try{
// //自定义一定要进行处理
// t.scoreCheck(score);
// }catch (ScoreException e){
// e.printStackTrace();
// }
}
}