◤5.1-5.2◢ 面向对象的概念
1.面向对象的三个特征:封装 、继承、多态。
2.举些生活中面向对象的例子。思路:应该结合面向过程来回答此题。
◤5.3◢ 类和对象的关系
1. 类是一种对事物的描述。
2.对象是指由这描述生产出来的实体。
例如:汽车图纸是类,由图纸制造出来的汽车就是对象。
c是一个类型为Car的变量。
◤5.4◢ 成员变量与局部变量
作用范围:成员变量作用于整个类中
局部变量作用于函数中,或者语句中。
在内存中的位置:
成员变量:在堆内存中,因为对象的存在,才在内存中存在
局部变量,存在栈内存中。
◤5.5◢匿名对象
与有名对象的区别:
例如:new Car().num=5; 但没办法做后继操作了,这就是与有名对象的区别
什么时候使用:
当对对象的方法只使用一次。
例:Car c=new Car(); show (c);
show(new Car()); //没办法再对这个对象再进行操作
◤5.6◢封装
概念: 是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处: 将变化隔离
便于使用
提高重用性
提高安全性
◤5.7◢private修饰符
private:私有修饰符:用于修饰类中的成员(成员变量,成员函数)。
私有只在本类中有效
将变量私有化以后,类以外即使建立了对象也不能直接访问,但需要在类中提供对应访问方式。
注意:私有仅仅是封装的一种表现形式。
之所以对外提供访问方式,就因为可以在访问方式中加入逻辑判断等语句。
对访问的数据进行操作,提高代码健壮性
一般有private 会有 set(){}和 get(){}
◤5.8◢构造函数
与一般函数的不同点:
格式:类名(){} //不用定义返回值,所以不可以写return
运行方式:一般函数是要调用才执行,一个对象可以调用多次
构造函数是一创建对象就执行,给对象进行初始化操作,每建立一个对象会执行且只执行一次。
什么时候定义构造函数?
当事物肯定具备一些特性或行为时,我们就可以将这些内容定义在构造函数内
◤5.9◢构造代码块
格式: { }//直接一个大括号,里面有执行语句
构造代码块优先于构造函数
构造代码块与构造函数的区别:
一个类中可以有很多重载的构造函数时,创建一个对象时便会有不执行的构造函数,
但构造代码块是无论创建什么对象,都会执行一次。
◤5.10-5.11◢this关键字
用途:区分同名的局部变量和成员变量
this代表的是谁?谁调用就代表谁。
需求:给人定义一个比较年龄是否相同的功能
public boolean compare (People p)
{
return this.age==p.age;
}
当定义类中的功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象,但凡本类功能内部使用了本类对象
◤5.12◢this在 构造函数间的互相调用
什么时候要用? 当一个类中的同名重载构造函数要互相调用时,不能用 类名();,而要用this();
注意:1.只用于同类中的构造函数中; 2 .只能放于第一行。
◤6.1◢static 关键字
static 静态
用法:是一个修饰符,用于修饰成员(成员变量,成员函数)
注意,修饰变量时一定要是成员变量,局部变量会报错
static修饰的成员可被类名调用,格式 : 类名.成员。
static修饰的成员特点:
1.随着类的加载而加载,也就是说会随着类的消失而消失,它的生命周期最长
2.优先于对象存在
3.被所有的对象所共享
4.可以被类名所调用
实例变量(成员变量)与类变量(静态)的区别
1.存放位置
类变量随着类的加载而存在于方法区中
实例变量随着对象的建立而存在于堆内存中
2.生命周期
类变量随着类的消失而消失
实例变量随着对象消失而消失
静态使用注意事项:
1.静态方法只能访问静态成员
非静态方法能访问静态也能访问非静态
2.静态方法中不可以定义this.super关键字
因为静态优先于对象存在,所以静态方法中不可以出现this,静态方法在类一被加载时就进了方法区,此时还没有对象。
3.主函数是静态
静态有利有弊
利:对对象的共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份
可以直接被类名调用。
弊:生命周期过长,访问出现局现性(静态虽好,只能访问静态)
什么时候使用静态
要从两方面下手:
因为静态修饰的内容有成员变量和成员函数。
1.什么时候定义静态变量呢?
当对象中出现共享数据时,该数据被静态所修饰
对象中的特有数据要定义成非静态存在于堆内存中
2.什么时候定义静态函数呢?
当功能内部没有访问到非静态数据(对象特有数据)//因为静态只能访问静态
那么该功能可能定义成静态函数
◤6.5◢帮助文档的制作 javadoc
格式:javadoc -d C:\myhelp -author -version ***.java
类必须是public 。
一个类中默认有一个空参数的构造函数,而且权限与所属类一样
◤6.6◢静态代码块
格式:static 特点:随着加载而执行,只执行一次不管创建几个对象都只执行一次
{
执行语句;
}
执行顺序:静态代码块>>>>>构造代码块>>>>>>构造函数
Person p=new Person();
/*这句话都做了什么
1.因为new用到了person.class.所以会先找到person.class文件并加载到内存中
2.执行该类中的static代码块,如果有的话,给person.class类进行初始化
3.在堆内存中开辟空间,分配内存地址
4.在堆内存中建立对象的特有属性,并进行默认初始化
5.对属性进行显示初始化
6.对对象进行构造代码块初始化
7.对对象进行对就的构造函数初始化
8.将内存地址付给栈内存中的p变量
◤6.8◢对象调用成员过程
◤6.9-6.10◢单例设计模式-----饿汉式:解决一个类在内存中只存在一个对象
思路:1.为了避免其它程序过多建立该类对象,先禁止其它程序建立该类对象-------------------将构造函数私有化
2.还为了让其他程序访问到该类对象,只好在本类中,自定义一个对象-------------------在类中创建一个本类对象
3.为了方便其它程序对自定义对象的访问,可以对外提供一些访问方式--------------------提供一个方法可以获取到该对象
class Single-----------------------------------饿汉式
{
private Single(){}
private static Single s=new Single();
public static Single get()
{return s;}
}
class Single1----------------------------------懒汉式(延时加载)
{
private Single1(){};
private static Single1 s=null;
public static Single1 get()
{
if(s==null)
s=new Single1();
return s;
}
}
重点:饿汉式和懒汉式有何不同?
1.饿汉式:Single类一加载进内存,就已经创建好了对象s
.懒汉式:对象的方法被调用时才初始化,也称延时加载,。single类进内存后,对象还没有存在,只有调 用get方法时,才建立对象
2.懒汉式存在安全问题,在多线程中懒汉式可能会出现两个对象,如果加个同步锁,则会使运行速度变慢
◤7.1-7.2◢继承
格式:类A extends 类B
继承:1.提高了代码的复用性。
2.让类与类之间产生了关系,有了这个关系才有了多态的特性
注意:
1.java中,继承只能单继承,不能多继承,因为存在安全问题:当多个父类中定义了相同功能,当功能内容不同时,子类对象不确定要运行哪一个。
但支持多层继承。
2.如何使用一个继承体系呢?想要使用体系先查阅体系父类的描述,因为你类中定义的是该体系中共性功能。
通过了解共性功能。就可以知道该体系的基本功能
那么这个体系已经可以基本使用了
那么在具体调用时,要创建最子类对象,因为有可能父类不能创建对象,创建子类对象可以使用更多的功能,包括基本的也包括特有的、
简单一句话:查阅父类功能,创建子类对象使用功能
◤7.3◢聚集:has a
聚合:球员和球队的关系,
组合:人和手的关系,相对较紧密
◤7.4-7.5◢子父类变量的特点
如果子类中出现非私有的同名成员变量时,
子类要访问本类中变量用this
子类要访问父类中的同名变量,用super
如果子类与父类的变量或函数一样,子类覆盖父类
覆盖: 1.子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败
2.静态只能覆盖静态
注意:
重载:只看同名函数的参数列表
重写:子父类方法要一模一样
父类中成员特点 是否创建子类对象 构造函数 构造代码块 静态代码块 是 执行 执行 执行 否,调用子类方法 不执行 不执行 执行
.子父类中的构造函数。
在对子类对象进行初始化时,父类的构造函数也会运行
那是因为子类的构造函数默认第一行有一条隐式语句 super();
super() 会访问父类中的空参数的构造函数,而且子类中所有的构造函数默认第一行都是super();
为什么子类一定要访问父类中的构造函数。
因为父类中的数据子类可以直接获取,所以子类对象在建立 时,需要先查看父类是如何对这些数据进行初始化的。
注意:super()只能放第一行,this()也只能放第一行
结论:子类的所有构造函数,默认都会访问父类中空参数的构造函数
因为子类每个构造函数内的第一行都有一句隐式super()
当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数
子类中至少会有一个构造函数会访问父类中构造函数。
◤7.7◢final关键字
1.可以修饰 类 函数 变量
2.final修饰的类不能被继承,为了避免被子类复写功能
3.被final修饰的方法不能覆盖
4.被final修饰的变量是一个常量只能被赋值一次,既可以修饰成员变量,也可以修饰局部变量,变成常量
当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字,方便于阅读
而这个值不需要改变,所以加上final修饰。作为常量:常量书写规范所有字母都大写,如果由多个单词组成。单词用_连接
5.内部类定义在类中的局部位置上时,只能访问局部被final修饰的局部变量
◤◢抽象类的特点:
1.抽象方法一定要在抽象类中
2.抽象方法和抽象类都必须被abstract修饰
3.抽象类不可以用new 创建对象,因为调用抽象方法没意义
4.抽象类中的方法要被使用,必须由子类复写所有的抽象方法后,建立子类对象调用
如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。
抽象类和一般类没有太大的不同。
该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂的东西。
这些不确定的部分,也是该事物的功能,需要明确出现,但是无法定义主体。
通过抽象方法来表示。
抽象类比一般类多了个抽象函数,就是在类中可以定义抽象方法,抽象类不可实例化
特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。
------------------------------------------------------------
/*假如我们在开发一个系统时需要对员工进行建模,员工包含3个属性:
姓名、工号以及工资。经理也是员工,除了含有员工的属性外,另外还有一个资金属性
请使用继承思想设计出员工类和经理类,要求类中提供必要的方法进行属性访问。
员工类(employee):name id pay
经理类(manage) :继承员工,并有自己特有的bonus*/
class Employee
{
private String name;
private String id;
private double pay;
Employee(String name,String id,double pay) //--------------------------构造函数后面有类型的话,子类不能省略super()
{
this.name=name;
this.id=id;
this.pay=pay;
}
public abstract void work(); //-------------------------------------------注意格式
}
class Manager extends Employee
{
private int bonus;
Manager(String name,String id,double pay,int bonus)//-------------------------------必须有
{
super(name,id,pay);
this.bonus=bonus;
}
public void work() -------------------------------------必须复写
{
System.out.println("MWK");
}
}
class AbstractTest
{
public static void main(String[] args)
{
Employee a=new Employee();
}
}
------------------------------------------------
/*
需求:获取一段程序运行时间
原理:获取程序开始和结束的时间并相减即可。
*/
abstract class GetTime
{
public final void getTime()//-----------------final修饰,为了不让覆盖
{
long start =System.currentTimeMillis();//-----------------------获取当前时间
runcode();
long end=System.currentTimeMillis();
System.out.println("毫秒:"+(end-start));
}
public abstract void runcode();//-------------------------抽象函数,让子类一定实现
}
class SubTime extends GetTime
{
public void runcode() //--------------------------------实现上面的抽象
{
for (int x=0;x<4000 ;x++ )
{
System.out.println(x);
}
}
}
class gettime1
{
public static void main(String[] args)
{
SubTime gt=new SubTime();
gt.getTime();
}
}
◤7.12-7.14◢接口
接口:初期理解,可以认为是一个特殊抽象类,当这抽象类只有抽象方法时,那么该类可以通过接口的形式表示。
interface用于定义接口
class 用于定义类
接口定义时,格式特点:
1.接口中常见定义:常量,抽象方法
2.接口中的成员都有固定修饰符
常量:public static final
方法:public abstract
记住:接口中的成员都是public的
interface Inter
{
public static final int NUM=3;
public abstract void show();//-----------------------接口中的方法是抽象方法
}
class Test implements Inter
{
public void show(){} //---------------------------------必须复写
}
class InterfaceDemo
{
public static void main(String[] args)
{
Test t=new Test();
System.out.println(t.NUM);
System.out.println(Test.NUM);
System.out.println(Inter.NUM);
}
}
◤接口的特点◢
implements 实现关系
接口:是不可以创建对象的,因为有抽象方法
需要被子类实现,子类对接口中的抽象方法全都覆盖后,子类才可以实例化
否则子类是一个抽象类。
-------------------
接口的特点:
接口与接口是继承关系
接口是对外暴露的规则
接口是程序的功能扩展
接口可以用来多实现
类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。
◤8.1-8.7◢多态
abstract class Animal
{
public abstract void eat();
public void show()
{System.out.println("8");}
}
class Cat extends Animal
{
public void eat()//----------------------子类实现父类时,权限一定要大于等于父类方法,而接口的方法有public,所以子类必须用public
{System.out.println("鱼");}
void catchMouse()
{System.out.println("鼠");}
}
class Dog extends Animal
{
public void eat()
{System.out.println("骨");}
void catchMouse()
{System.out.println("家");}
}
public class 多态 {
public static void main(String[] args)
{
/*Animal a=new Cat();
a.eat();
Animal b=new Dog();
b.eat();*/
function(new Cat());//----------------这就是多态的表现:以后可以还有更多的动物,但只要再加个类,然后function(new XX)就行
function(new Dog());
}
public static void function(Animal q)
{
q.eat();
}}
多态的体现
父类引用指向了自己的子类对象
父类的引用也可以接收自己的子类对象,
多态的前提
必须有继承或实现关系
通常还有一个前提:存在覆盖
多态的好处
多态的出现大大提高扩展性
多态的弊端:
但是只能使用父类的引用访问父类中的成员
多态的应用
在多态中非静态成员函数的特点
1.在编译时期:参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过,如果没有,编译失败
2.在运行时期:参阅对象所属的类中是否有调用的方法
编译是否成功看左边,运行时看右边的方法。
3..多态中成员变量的特点,都参考左边。
4.静态函数:编译运行都看左边。
1.子类实现父类时,权限一定要大于等于父类方法,而接口的方法有public,所以子类必须用public
interface PCI----------------------------------------------------接口
{
public void open();
public void close();
}
class MainBoard-----------------------------------主板一启用,就启用接口
{
public void run()
{
System.out.println("mainboard run");
}
public void usePCI(PCI p)
{
p.open();
p.close();
}
}
class NetCard implements PCI---------------------------------------所以主板一运行,网卡就运行
{
public void open()
{
System.out.println("net run");
}
public void close()
{
System.out.println("net close");
}
}
public class 主态的主板例子
{
public static void main(String[] args)
{
MainBoard mb=new MainBoard();
mb.run();
mb.usePCI(new NetCard());
◤8.8-8.9◢ Object类
1.equals() 比较在内存中位置是否一致,如果一致返回true.
用equals(Object obj){}重写方法,String中的equals()已复写过。
2.toString()
内部类:
将一个类定义在另一个类的里面,对里面那个类就成为内部类(内置类,嵌套类)。
◤9.1◢、内部类的访问规则:
内部类可以直接访问外部类中的成员,包括私有;
之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this
外部类要访问内部类,必须建立内部类对象。
访问格式:
当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中。
可以直接建立内部类对象。
Outer.Inner in = new Outer().new Inner();
◤9.2◢ 静态内部类
当内部类在成员位置上,就可以被成员修饰符所修饰。
比如:private:将内部类在外部类中进行封装。
static:内部类就具备了static特性
当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。
在外部其他类中,如何访问内部类的非静态成员呢?
new Outer.Inner().function(); 非静态
在外部其他类中,如何直接访问static内部类的静态成员呢?
Outer.Inner.function(); 静态
注意:当内部类中定义了静态成员,该内部类必须是static的。
当外部类中的静态方法访问内部类时,内部类也必须是static的。
◤9.3◢ 内部类定义原则
当描述事物时,事物的内部还有事物,该事物用内部类来描述,因为内部事务在使用外部事物的内容。
class Outer
{
private int x = 3;
static class Inner//静态内部类
{
int x =4;
void function()
{
int x = 6;
System.out.println("Inner:"+Outer.this.x);//访问外部类时需要外部类的引用
}
}
void method()
{
Inner in = new Inner();
in.function();
}
}
class InnerClassDemo
{
public static void main(String[] args)
{
new Outer.Inner().function();
//Outer out = new Outer();
//out.method();
//直接访问内部类中的成员
//Outer.Inner in = new Outer().newInner();//外部类名.内部类名 变量名 =外部对象.内部对象
//in.function();
}
}
class Outer
{
private int x = 3;
static class Inner//静态内部类
{
int x =4;
void function()
{
int x = 6;
System.out.println("Inner:"+Outer.this.x);//访问外部类时需要外部类的引用
}
}
void method()
{
Inner in = new Inner();
in.function();
}
}
class InnerClassDemo
{
public static void main(String[] args)
{
new Outer.Inner().function();
//Outer out = new Outer();
//out.method();
//直接访问内部类中的成员
//Outer.Inner in = new Outer().newInner();//外部类名.内部类名 变量名 =外部对象.内部对象
//in.function();
}
}
5、内部类定义在局部时,(如内部类存在于外部类的方法中)
1.不可以被成员修饰符修饰
2..可以直接访问外部类中的成员,因为还持有外部类中的引用。
但是不可以访问它所在局部中的变量,只能访问被final修饰的局部变量。
class Outer
{
int x=3;
void method(final int a)
{
class Inner
{
final int y = 4;//内部类只能访问被final修饰的局部变量
void function()
{
System.out.println(a);
}
}
new Inner().function();//调用Inner内部类时必须将其放在内部类的后面,方便JVM识别
}
}
class InnerClassDemo2
{
public static void main(String[] args)
{
Outer out = new Outer();
out.method(7);
out.method(8);//这里程序能够正常运行,因为局部成员进栈运行完后,栈内存会被自动释放,因此可以重新定义局部成员的值
}
}
class Outer
{
int x=3;
void method(final int a)
{
class Inner
{
final int y = 4;//内部类只能访问被final修饰的局部变量
void function()
{
System.out.println(a);
}
}
new Inner().function();//调用Inner内部类时必须将其放在内部类的后面,方便JVM识别
}
}
class InnerClassDemo2
{
public static void main(String[] args)
{
Outer out = new Outer();
out.method(7);
out.method(8);//这里程序能够正常运行,因为局部成员进栈运行完后,栈内存会被自动释放,因此可以重新定义局部成员的值
}
}
◤9.4◢、匿名内部类:
1.匿名内部类其实就是内部类的简写格式。
2.定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。
3.匿名内部类的格式: new 父类或者接口(){定义子类的内容}
4.其实匿名内部类就是一个匿名子类对象,而且这个对象有点“胖”,也可以理解为带内容的对象。
5.匿名内部类中定义的方法最好不要超过3个。
6.定义匿名内部类,就是为了简化书写,覆盖方法。
abstract class AbsDemo
{
abstract void show();
}
class Outer
{
int x = 3;
public void function()
{
new AbsDemo()
{
voidshow()
{
System.out.println("x===="+x);
}
}.show();
}
}
class InnerClassDemo3
{
public static void main(String[] args)
{
new Outer().function();
}
}
abstract class AbsDemo
{
abstract void show();
}
class Outer
{
int x = 3;
public void function()
{
new AbsDemo()
{
voidshow()
{
System.out.println("x===="+x);
}
}.show();
}
}
class InnerClassDemo3
{
public static void main(String[] args)
{
new Outer().function();
}
}分析:内部类都做了什么事情?
1.它继承了一个类
2.它进行了复写
3.创建对象
4.进行调用
new AbsDemo(){void show()}.show();
练习:
interface Inter
{
void method();
}
class Test
{
/*
static class Inner implements Inter
{
public void method()
{
System.out.println("methodrun");
}
}
*/
//补足代码,使用匿名内部类
static Inter function()
{
return new Inter()//Inner
{
public void method()
{
System.out.println("method run");
}
};
}
}
class InnerClassTest
{
public static void main(String[] args)
{
//Test.function():Test 类中有一个静态的方法function。
//.method():function这个方法运算后的结果是一个对象,而且是一个Inter类型的对象。
//因为只有是Inter类型的对象,才可以调用method方法。
Test.function().method();
/*
Inter in = Test.function();
in.method();
*/
}
}
interface Inter
{
void method();
}
class Test
{
/*
static class Inner implements Inter
{
public void method()
{
System.out.println("methodrun");
}
}
*/
//补足代码,使用匿名内部类
static Inter function()
{
return new Inter()//Inner
{
public void method()
{
System.out.println("method run");
}
};
}
}
class InnerClassTest
{
public static void main(String[] args)
{
//Test.function():Test 类中有一个静态的方法function。
//.method():function这个方法运算后的结果是一个对象,而且是一个Inter类型的对象。
//因为只有是Inter类型的对象,才可以调用method方法。
Test.function().method();
/*
Inter in = Test.function();
in.method();
*/
}
}
◤9.5◢异常
1、异常的体系
Error:
1.通常出现重大问题如:运行的类不存在或者内存溢出等。
2.不编写针对代码对其处理
Exception:
1.在运行时出现的一些情况,可以通过try catch finally
Exception 和Error的子类名都是以父类名作为后缀。
异常:就是程序在运行时出现不正常情况。
异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述,并封装成对象。其实就是java对不正常情况进行描述后的对象体现。
对于问题的划分为两种:一种是严重的问题,一种是非严重的问题。
对于严重的,java通过Error类进行描述。
对于Error一般不编写针对性的代码对其进行处理。
对于非严重的,java通过Exception类进行描述。
对于Exception可以使用针对性的处理方式进行处理。
无论Error或者Exception都具有一些共性内容。比如:不正常情况的信息,引发原因等。
Throwable
Error
Exception
◤9.6◢、异常的处理
java提供了特有的语句进行处理
try{
需要被检测的代码
}
catch(异常类变量){
处理异常的代码:(处理方式)
}
finally{
一定会执行的语句;
}
3、对捕获到的异常对象进行常见方法操作
StringgetdMessage();获取异常信息。
◤9.7◢ 在函数上声明异常:
便于提高安全性,让调用者进行处理,不处理编译失败。
◤9.8◢对多异常的处理。
1.声明异常时,建议声明更为具体的异常,这样处理的可以更具体。
2.对方声明几个异常,就对应有几个catch块。不要定义多余的catch块
如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面
建议在进行catch处理时,catch中一定要定义具体处理方式。
不要简单定义一句e.printStackTrace();也不要简单的就书写一条输出语句。
class Demo
{
int div(int a,int b)throws ArithmeticException,ArrayIndexOutOfBoundsException//在功能上通过throws的关键字声明了该功能有可能会出现问题。
{
int[] arr = new int[a];
System.out.println(arr[4]);
return a/b;
}
}
class ExceptionDemo
{
public static void main(String[] args) //throws Exception
{
Demo d = new Demo();
try
{
int x = d.div(5,0);
System.out.println("x="+x);
}
catch (ArithmeticExceptione)//Exception e = newArithmeticException();
{
System.out.println("除零了");
//System.out.println(e.getMessage());// /by zero;
System.out.println(e.toString());//异常名称:异常信息
//e.printStackTrace();//异常名称,异常信息,异常出现的位置。
//其实JVM默认的异常处理机制,就是在调用printStrackTrace方法。
//打印异常的堆栈的跟踪信息。
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println(e.toString());
System.out.println("角标越界啦!!");
}
System.out.println("over");
}
}
class Demo
{
int div(int a,int b)throws ArithmeticException,ArrayIndexOutOfBoundsException//在功能上通过throws的关键字声明了该功能有可能会出现问题。
{
int[] arr = new int[a];
System.out.println(arr[4]);
return a/b;
}
}
class ExceptionDemo
{
public static void main(String[] args) //throws Exception
{
Demo d = new Demo();
try
{
int x = d.div(5,0);
System.out.println("x="+x);
}
catch (ArithmeticExceptione)//Exception e = newArithmeticException();
{
System.out.println("除零了");
//System.out.println(e.getMessage());// /by zero;
System.out.println(e.toString());//异常名称:异常信息
//e.printStackTrace();//异常名称,异常信息,异常出现的位置。
//其实JVM默认的异常处理机制,就是在调用printStrackTrace方法。
//打印异常的堆栈的跟踪信息。
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println(e.toString());
System.out.println("角标越界啦!!");
}
System.out.println("over");
}
}
◤9.9◢、自定义异常:必须是自定义类继承Exception
因为项目中会出现特有问题,而这些问题并未被java锁描述并封装对象,所以对于这些特有的问题可以按照java的对问题封装的思想,将特有的问题,进行自定义的异常封装。
当在函数内部出现了throw抛出异常对象时,那么就必须要给对应的处理动作,
要么在内部try catch处理;要么在函数上声明让调用者处理。
一般情况下,函数内出现异常,函数上需要声明。
发现打印的结果中只有异常的名称,却没有异常的信息,因为自定义的异常并未定义信息。
如何定义异常信息呢?
因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时,将异常信息传递给父类通过super语句,那么就可以直接通过getMessage方法获取自定义的异常信息。
继承Exception原因:
异常体系有一个特点:因为异常类和异常对象都被抛出。
他们都具备可抛性。这个可抛性是Throwable这个体系中独有特点。只有这个体系中的类和对象才可以被throws和throw操作。
需求:在本程序中,对于除数是负数的,也视为是错误的是无法进行运算的,那么就需要对这个问题进行自定义描述。
[java] view plaincopyprint?class FuShuException extends Exception//自定义异常必须集成Exception体系
{
private int value;
FuShuException(Stringmsg,int value)
{
super(msg);
this.value = value;
}
public int getValue()
{
return value;
}
/*private String msg;
FuShuException(Stringmsg)
{
this.msg = msg;
}
public String getMessage()
{
return msg;
}
*/
}
class Demo
{
int div(int a,int b)throws FuShuException//在功能上通过throws的关键字声明了该功能有可能会出现问题。
{
if(b<0)
throw new FuShuException("出现了除数是负数的情况/ by fushu",b);//手动通过throw关键字抛出一个自定义异常。
return a/b;
}
}
class ExceptionDemo2
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
int x = d.div(4,-1);
System.out.println("x="+x);
}
catch (FuShuException e)
{
System.out.println(e.toString());
System.out.println("出现错误的负数是:"+e.getValue());
}
System.out.println("over");
}
}
class FuShuException extends Exception//自定义异常必须集成Exception体系
{
private int value;
FuShuException(Stringmsg,int value)
{
super(msg);
this.value = value;
}
public int getValue()
{
return value;
}
/*private String msg;
FuShuException(Stringmsg)
{
this.msg = msg;
}
public String getMessage()
{
return msg;
}
*/
}
class Demo
{
int div(int a,int b)throws FuShuException//在功能上通过throws的关键字声明了该功能有可能会出现问题。
{
if(b<0)
throw new FuShuException("出现了除数是负数的情况/ by fushu",b);//手动通过throw关键字抛出一个自定义异常。
return a/b;
}
}
class ExceptionDemo2
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
int x = d.div(4,-1);
System.out.println("x="+x);
}
catch (FuShuException e)
{
System.out.println(e.toString());
System.out.println("出现错误的负数是:"+e.getValue());
}
System.out.println("over");
}
}
◤9.10◢、throws和throw的区别:
1.throws使用在函数上;
2.throw使用在函数内;
3.throws后面跟的是异常类,可以跟多个,用逗号隔开;
4.throw后跟的是异常对象。
◤9.11◢、RuntimeException异常
Exception 中有一个特殊的子类异常RuntimeException运行时异常。
如果在函数内容抛出该异常,函数上可以不用声明,编译一样通过。
如果在函数上声明了该异常,调用者可以不用进行处理。编译一样通过。
之所以不用在函数上声明,是因为不需要让调用者处理。当该异常发生,希望程序停止。因为在运行时,出现了无法继续运算的情况,希望停止程序后,并对代码进行修正。
自定义异常时,如果该异常的发生,无法再继续进行运算,那么就让自定义异常继承RuntimeException。
class FuShuException extendsRuntimeException
{
FuShuException(Stringmsg)
{
super(msg);
}
}
class Demo
{
int div(int a,int b)//throws ArithmeticException
{
if(b<0)
thrownew FuShuException("除数出现负数了!");
else if(b==0)
thrownew ArithmeticException("被零除啦!!");
return a/b;
}
}
class ExceptionDemo3
{
public static void main(String[] args)
{
Demo d = new Demo();
int x = d.div(4,-1);
System.out.println("x="+x);
System.out.println("over");
}
}
/*
class Person
{
public void checkName(String name)
{
if(name.equals("lisi"))//NullPointerException
if("lisi".equals(name))//if(name!=null && name.equals("lisi"))
System.out.println("Yes");
else
System.out.println("No");
}
}
class TestException
{
public static void main(String[] args)
{
Person p = new Person();
p.checkName(null);
}
}
*/
class FuShuException extendsRuntimeException
{
FuShuException(Stringmsg)
{
super(msg);
}
}
class Demo
{
int div(int a,int b)//throws ArithmeticException
{
if(b<0)
thrownew FuShuException("除数出现负数了!");
else if(b==0)
thrownew ArithmeticException("被零除啦!!");
return a/b;
}
}
class ExceptionDemo3
{
public static void main(String[] args)
{
Demo d = new Demo();
int x = d.div(4,-1);
System.out.println("x="+x);
System.out.println("over");
}
}
/*
class Person
{
public void checkName(String name)
{
if(name.equals("lisi"))//NullPointerException
if("lisi".equals(name))//if(name!=null && name.equals("lisi"))
System.out.println("Yes");
else
System.out.println("No");
}
}
class TestException
{
public static void main(String[] args)
{
Person p = new Person();
p.checkName(null);
}
}
*/总结:
可处理的用Exception,不可处理的则用RuntimeException
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
◤10.1◢异常-finally
finally代码块:定义一定执行的代码,通常用于关闭资源。
class FuShuException extends Exception
{
FuShuException(String msg)
{
super(msg);
}
}
class Demo
{
int div(int a,int b)throws FuShuException
{
if(b<0)
throw new FuShuException("除数为负数");
return a/b;
}
}
class ExceptionDemo4
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
intx = d.div(3,-1);
System.out.println("x="+x);
}
catch (FuShuException e)
{
System.out.println(e.toString());
return;
}
finally
{
System.out.println("finally");//finally中存放的是一定会被执行的代码
}
System.out.println("over");
}
}
class FuShuException extends Exception
{
FuShuException(String msg)
{
super(msg);
}
}
class Demo
{
int div(int a,int b)throws FuShuException
{
if(b<0)
throw new FuShuException("除数为负数");
return a/b;
}
}
class ExceptionDemo4
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
intx = d.div(3,-1);
System.out.println("x="+x);
}
catch (FuShuException e)
{
System.out.println(e.toString());
return;
}
finally
{
System.out.println("finally");//finally中存放的是一定会被执行的代码
}
System.out.println("over");
}
}
◤10.2◢、异常处理语句的几种格式:
第一种格式:
try{
}
catch (){
}
//第二种格式:
try{
}
catch (){
}
finally{
}
//第三种处理格式:
try{
}
finally{
}
//记住一点:catch是用于处理异常。如果没有catch就代表异常没有被异常处理过,
//如果该异常时检测时异常,那么久必须声明。
◤10.3◢、异常在子父类覆盖中的体现:
1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类。
2.如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。
3.如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。如果子类方法发生了异常,就必须要进行try处理,绝对不能抛。
◤10.5◢异常总结:
异常:是什么?是对问题的描述,将问题进行对象的封装。
异常体系:
Throwable
Error
Exception
RuntimeException
异常体系的特点:异常体系中的所有类以及建立的对象都具备可抛性,也就是说可以被throw和throws关键字所操作。只有异常体系具备这个特点。
当函数内容有throw抛出异常对象,并为进行try处理,必须要在函数上声明。否则编译失败。
注意,RuntimeException除外,也就说,函数内如果抛出的RuntimeException异常,函数上可以不用声明。
如果函数声明了异常,调用者需要进行处理,处理方法可以throw,可以try
异常有两种:
编译时被检测异常:
该异常在编译时,如果没有处理(没有throw也没有try),编译失败。
该异常被标识,代表这可以被处理。
运行时异常(编译时不检测)
在编译时,不需要处理,编译器不检查。
该异常的发生,建议不处理,让程序停止,需要对代码进行修正。
注意:
1.finally中定义的通常是关闭资源代码,因为资源必须被释放。
2.只有当遇到System.exit(0);语句是,系统会退出,finally才不会被执行。
3.当catch语句中遇到return时,JVM会检查catch后有没有finally,如果有,则执行finally中的语句,然后退出;如果没有,则直接退出。
6、自定义异常:
定义类继承Exception或者RuntimeException
1.为了让该自定义类具备可抛性;
2.让该类具备操作异常的共性方法。
当要定义自定义异常的信息时,可以使用父类已经定义好的功能。
将异常信息传递给父类的构造函数。
classMyException extends Exception
{
MyException(String message)
{
super(message);
}
}
自定义异常:是按照java的面向对象思想,将程序中出现的特有问题进行封装。
异常的好处:
1.将问题进行封装;
2.将正常流程代码和问题处理代码相分离,方便与阅读。
异常的处理原则:
1.处理方式有两种:try或者throw。
2.调用到抛出异常的功能时,抛出几个,就处理几个。一个try对应多个catch的情况。
3.多个catch,父类的catch要放在最下面。
4.catch内,需要定义针对性的处理方式,不要简单的定义printStackTrace,输出语句,也不要不写。当捕获到的异常,本功能处理不了时,可以继续在catch中抛出:
try
{
throw new AException();
}
catch (AException e)
{
throw e;
}
如果该异常处理不了,但并不属于该功能出现的异常。
可以将异常转换后,在抛出和该功能相关的异常。
或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去,
让调用者知道,并处理,也可以将捕获异常处理后,转换型的异常。
try
{
throw new AException();
}
catch (AException e)
{
//throwAException();对AException处理。
throw new BException();
}
异常的注意事项:
在子父类覆盖时:
1.子类抛出的异常必须是父类的异常的子类或者子集;
2.如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能抛。
其实就是子类不能比父类抛出更多异常!
面试题:写出this关键字的含义,final有哪些特点?
this:代表本类对象,哪个对象调用this所在的函数,this就代表哪个对象。
final:
1.修饰类,变量(成员变量,静态变量,局部变量),函数。
2.修饰的类不可以被继承;
3.修饰的函数不可以被覆盖
4.修饰的变量时一个常量,只能赋值一次。
5.内部类只能访问局部变量中被final修饰的变量
◤10.7◢、包(package)
对类文件进行分类管理
给类提供多层命名空间
写在程序文件的第一行
类名的全称是:包名.类名
包也是一种封装形式。
jar包
1.方便项目的携带。
2。方便于使用,只要在classpath设置jar路径即可。
3.数据库驱动,SSH框架等都是jar包体现的。
需要查看或者运行Jar包的时候,需要先将classpath路径设置成Jar包路径,
例如:setclasspath=c:\myclass\haha.jar
编译:javac -d 路径 类名.java
javac -d c:\myclass PackageDemo.java 或者javac -d . PackageDemo.java 中间的.是指当前路径
-d:指定包所存放的位置
运行:java 包名.类名
java pack.PackageDemo
◤10.8◢包与包之间访问
为了简化类名的书写,使用了一个关键字:import。
import导入的是包中的类。
建议不要写通配符*,需要用到包中的哪个类,就导入哪个类。
建议包名不要重复,可以使用url来完成定义,url是唯一的。
package pack;
import packb.haha.hehe.heihei.*;
class PackageDemo
{
publicstatic void main(String[] args)
{
packa.DemoA d = new packa.DemoA();
d.show();
//packb.DemoB d = new packb.DemoB();
//d.method();
}
}
package pack;
import packb.haha.hehe.heihei.*;
class PackageDemo
{
publicstatic void main(String[] args)
{
packa.DemoA d = new packa.DemoA();
d.show();
//packb.DemoB d = new packb.DemoB();
//d.method();
}
}
错误原因:packa包不在当前目录下
需要设置classpath,告诉jvm去哪里找指定的packa包。
有了包,范围变大,一个包中的类要被访问,必须要有足够大的权限,所以被访问的的类要被public修饰
类共有后,被访问的成员也要共有才可以被访问。
总结:
包与包之间进行访问,被访问的包中的类以及类中的成员,需要public修饰。
不同包中的子类还可以直接访问父类中被protected权限修饰的成员
包与包之间可以使用的权限只有两种:public protected
public protected default private
同一个类中 ok ok ok ok
同一个包中 ok ok ok
子类 ok ok
不同包中 ok
注意:当想建立一个包中的两个不同类而防止在编译的时候被覆盖,这里可以将另一个类在新建的java文档里添加同名包名,这样编译的时候就不会覆盖原始类产生的class文件。
◤10.9◢、导入import
为了简化类名的书写,使用一个关键字,import;
例如:import packb.haha.hehe.heihei.DemoC;
◤10.10◢、Jar包
1、Java的压缩包
1.方便项目的携带;
2.方便于使用,只要在classpath设置jar路径即可;
3.数据库驱动,SSH框架等都是以jar包体现的。
2、如何创建jar包?
格式:jar -cfxx.jar 包名,前提是需要切换到打包路径中,且路径中已经存在相应包文件
jar -cf haha.jar packa pack
3、jar命令常见用法:
-c:创建新的归档文档;
-f:指定归档文件名
-t:列出归档目录
-v:在标准输出中生成详细输出
当使用jar命令打包程序后,jar包文件中会有一个配置清单文件
设置jar包的classpath路径方式为setclasspath=c:\myclass\haha.jar
将jar包中的详细信息写入硬盘中的一个文件里,操作如下:
jar -tf a.jar >c:\1.txt