-----------android培训、java培训、java学习型技术博客、期待与您交流!---------
多态
定义:某一种事物的多种存在形态
1. 多态的体现形式:
父类的引用指向了自己的子类对象。父类的引用也可以接受自己的子类对象。
2. 多态的前提
必须是类与类之间有关系,要么继承,要么实现,通常还有一个前提:存在覆盖。
3. 多态的好处
多态的出现提高了程序的扩展性。
4. 多态的弊端
虽然多态提高了扩展性,但是只能使用父类的引用访问父类中的成员。
如果想调用特有方法要如何操作?
强制转换:将父类引用,转换成子类类型。
千万不要出现把父类对象转换成子类类型。
我们能转换的是父类引用指向了自己的子类对象时, 该引用可以被提升(多态),也可以被强制转换。
多态自始至终都是子类对象在做变化。
如下面的程序所示
/*
多态的使用示例
我现在身边正好有一瓶可乐,就用可乐举例啦
*/
//定义一个饮料父类
abstract class Drinsk
{
//定义一个糖浆方法,因为不知道是那种糖浆的饮料,所以是抽象方法,抽象类
abstract void syrup();
}
//定义一个可乐类,继承饮料类
class Coke extends Drinks
{
//重写糖浆方法,定义可乐的方法体
public void syrup()
{
System.out.println("可乐糖浆");
}
//定义可乐的特有方法
public void color()
{
//可乐是黑的色
System.out.println("黑色");
}
}
class DuoTaiDemo
{
public static void main(String[] args)
{
//这就是多态,父类的引用指向子类对象
Drinks d = new Coke();
//调用父类中的方法
d.syrup();
//父类的引用不可以调用子类的方法,所以要进行强制转换
//将父类的引用转换成子类类型
Coke c = (Coke)d;
//这时再调用子类中的方法就可以了
c.color();
}
}
运行结果为
5. 多态的应用:
思想:多态将对象调用这件事变简单了,以前是指挥每一个对象做事,现在是指挥一批对象做事。 因为找到了这些对象的共同所属类型。
记住:只要把事物不断的向上抽取,总能找到共同点,找到后就可以统一操作很多对象。
我们对类型进行抽取,导致了多态的产生,操作一个大类型,对大类型中所有小类型都能进行操作,
这就是多态的核心思想。因为这个思想,才可以提高扩展性。
理解:就比如刚才的例子,糖浆就是抽取的共性,所有饮料都有糖浆, 黑色就是事物特有的,
我们既可以输出糖浆,也可以输出黑色。
在多态中成员函数的特点
在编译时期
参阅引用型变量所属的类中是否有调用的方法, 如果有,编译通过。如果没有,编译失败。
在运行时期
参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时编译看等号左边,运行看等号·右边。(如果右边所属的类没有该方法,就去父类找)
以下是面试中考到到的知识点,需注意!!!!
在多态中成员变量的特点
(子父类中有同名的成员变量时)无论编译和运行,都参考左边(引用变量所属的类)
在多态中静态成员函数的特点
(子父类中有同名静态成员函数时)无论编译和运行,都参考左边(引用型数据变量所属的类)
也就是父类的引用在调用静态成员函数时,被调用的是父类中的静态函数。
原因:
因为是静态,所以在类建立时静态方法就已经存在,不需要对象直接用类名调用即可。
当父类引用指向子类对象时,只要是父类的所属引用,就会用父类的静态方法。
调用那个类中的静态成员方法看的是引用型变量所属类的内容。
因为静态成员函数比对象先加载,所以调用的静态成员函数不属于对象。
instanceof
它的作用是判断其左边对象是否为其右边类的实例。
返回boolean类型的数据。可以用于判断继承中子类的实例是否为父类的实现。
instanceof 不经常使用,使用的情况如下:
1. 子类类型有限时。
2. 当传的类型需要进行其他操作,如:比较
必须要确定是哪种子类型,要调用特有方法来比较,这时会用instanceof判断一下。
下面我们来看一个多态的实例
/*
多态示例
手机的运行实例。
手机的运行由手机的主板控制,我们都知道在智能手机还没有被发明出来的年代
手机只能简单的运行,打电话,发短信等操作,到了智能手机时代手机就可以照相,听音乐了。
我们可以把手机的主板当做一个底座,底座上面有可以安装耳机孔和摄像头的凹槽,
而这个凹槽呢有特殊的形状,只要符合这个形状的耳机孔和摄像头都可以在这个手机主板上使用,
这样就降低了他们之间的耦合性。下面我们来用程序体现。
*/
//定义凹槽接口,用来接收耳机孔,摄像头等外接设备
interface AoCao
{
//定义凹槽的通电和断电方法。
public abstract void open();
public abstract void close();
}
//定义耳机孔类,实现凹槽接口
class ErJiKong implements AoCao
{
//因为接口的成员函数都是public修饰的,复写方法需要权限比被覆盖的方法大或一样 所以public修饰
//复写凹槽的通电断电方法
public void open()
{
System.out.println("耳机孔通电————听音乐");
}
public void close()
{
System.out.println("耳机孔断电");
}
}
//定义摄像头类,实现凹槽接口
class SheXiangTou implements AoCao
{
//复写通电断电方法
public void open()
{
System.out.println("摄像头通电——————照相");
}
public void close()
{
System.out.println("摄像头断电");
}
}
//定义手机类
class Phone
{
//按了开机键,手机开机
public static void run()
{
System.out.println("手机开机");
}
//定义使用凹槽方法,接收凹槽对象,但其实我们知道凹槽不能创建对象,所以实际运用中接受的是凹槽的子类对象
//其实就是:AoCao Ao = new ErJiKong() 这就是多态,父类的引用指向了子类对象
public static void useAoCao(AoCao ao)
{
//判断传入的对象是否属于凹槽接口,或者它的子类。
if(ao instanceof AoCao)
{
//调用通电,断电方法。通过刚才我们学的,对于多态中的成员方法,编译看左边,运行看右边
//左边引用类型所属的类是凹槽接口(父类),有这两个方法,编译可以通过
//右边对象所属的类会是凹槽接口的子类,都复写了这两个方法,所以运行时就运行子类中的通电断电方法。
ao.open();
ao.close();
}
}
}
class PhoneDemo
{
public static void main(String[] args)
{
//创建一个手机对象
Phone p=new Phone();
//手机开机运行
p.run();
//将耳机孔对象作为参数传入使用凹槽方法中,使用耳机孔听歌。
p.useAoCao(new ErJiKong());
将摄像头对象作为参数传入使用凹槽方法中,使用摄像头拍照。
p.useAoCao(new SheXiangTou());
}
}
程序运行结果
内部类
内部类:将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)。
个人理解:类是用来描述事物的,事物中还有事物,该事物就用内部类来描述,就比如:
我现在打字的键盘是一个事物,而每个按键又是一个事物, 这是可以再键盘这个类中,定义一个按键内部类,来描述按键。
内部类访问特点
1. 内部类可以直接访问外部类成员,包括私有成员,
之所以可以访问外部类的成员,是因为内部类中持有了一个外部类的引用,
格式:外部类名.this
2. 外部类要访问内部类中的成员,必须要建立内部类的对象。
访问格式
1. 当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中直接建立内部对象。
格式: 外部类名.内部类名 引用变量名 = 外部类对.内部类对象
如: Outer.Inner in =new Outer().new Inner();
当内部类在成员位置上,就可以被成员修饰符所修饰
比如:private:将内部类在外部类中进行封装;
static:内部类就具备了static的特性,当内部类被static修饰后, 只能访问外部类中的static成员,出现了访问局限。
在外部其他类中如何直接访问static内部类的非静态成员?
格式: new 外部类名.内部类名().方法();
如: new Outer.Inner().funvtion();
在外部其他类中如何直接访问static内部类的静态成员呢?
格式: 外部类名.内部类名
如: Outer.Inner.function();
注意:当内部类中定义了静态成员,该内部类必须是静态的
当外部类中的静态方法访问内部类时,内部类也必须是静态的
2. 内部类定义在局部时
a. 不可以被成员修饰符修饰。
b. 可以直接访问外部类中的成员,因为还持有外部类的引用。但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量
下面我们来看一个内部类的例子
因为我是先看完的视频才写的博客,所以这里的例子我想用基础测试中的题
/*
内部类代码演示
定义一个包含私有成员变量和函数的类,再定义一个内部类,在内部类函数中访问外部成员变量,
并调用外部函数。在外部类函数中创建内部类对象,调用内部类函数。
*/
class InnerClassDemo
{
public static void main(String[] args) {
//调用外部类的方法来完成程序的检验
//因为每一步前我都加了输出代码,可以很清楚的看到整个程序的步骤和过程。
OuterClass.outerMethod2();
}
}
//为了老师阅读起来比较方便新建一个名叫OuterClass的类,用于题目的完成
class OuterClass{
//定义这个类中的私有成员变量
private static int i = 123;
//定义类中的私有方法
private static void outerMethod1(){
//输出“我是OuterClass类中的私有函数”,输出了,证明方法被调用
System.out.println("我是OuterClass类中的私有函数~");
}
//定义内部类
public class InnerClass{
//定义一个方法,用于访问外部类的成员变量和调用外部类的方法
public void innerMethod(){
//输出内部类方法在被调用的语句,告诉用户内部类调用成功
//先给后面调用外部类私有成员的语句铺垫一下,说明一下先后顺序
System.out.println("内部类的方法正在被调用,内部类方法正在调用外部类的私有成员:");
//输出外部类的私有成员变量
System.out.println("外部类的私有成员变量:"+i);
//调用外部类的私有方法,因为是静态的,直接调用即可
outerMethod1();
}
}
//在外部类中定义一个方法,用于创建内部类对象,调用内部类函数
public static void outerMethod2(){
//输出语句“外部类的方法被调用了”
System.out.println("外部类的方法被调用啦~");
//输出创建对象内部类对象的语句
System.out.println("在外部类中创建内部类对象......");
//创建内部类对象,因为内部类在外部类中,所以要如以下方法创建内部类对象
InnerClass innerClass = new OuterClass().new InnerClass();
//输出内部类对象调用外部类私有方法的语句
System.out.println("内部类对象调用自己的方法啦~");
//内部类的对象调用内部类的函数
innerClass.innerMethod();
}
}
运行结果
匿名内部类
特点:
1. 匿名内部类其实就是内部类的简写格式
2. 定义匿名内部类的前提:内部类必须继承一个类或者实现接口
3. 匿名内部类的格式: new 父类或者接口 .(){定义子类的内容}
4. 其实匿名内部类就是一个匿名子类对象,而且这个对象有点儿“胖”。可以理解为带内容的对象
5. 匿名内部类中定义的方法最好不要超过三个,因为定义太多方法会没有阅读性。
好处:简化书写
缺点:
1. 不能直接调用自己的特有方法
2. 不能做强转动作。
3. 如果继承的父类或接口中有很多方法时,使用匿名内部类阅读性会非常差,且调用会很麻烦。
所以匿名内部类中定义的方法有一般不超过3个。
使用匿名内部类的场景之一
当使用的方法的参数类型是一个接口类型时,该接口中的方法不超过三个
可以定义一个匿名内部类,把匿名内部类作为参数传入。
匿名内部类的应用
/*
匿名内部类使用示例
*/
//定义一个接口
interface Inter
{
//定义一个方法
public abstract void method();
}
class InnerClassDemo2
{
public static void main(String[] args)
{
//调用show方法。因为接口不能创建对象,所以使用匿名内部类
//就当匿名内部类就是Inter的子类,并复写Inter接口中的方法
show(new Inter()
{
public void method()
{
System.out.println("匿名内部类中方法在被调用");
}
});
}
//定义一个show方法,接收Inter对象
public static void show(Inter in)
{
//调用Inter类中方法
in.method();
}
}
下面我们来看一个小练习
/*
内部类小练习
*/
//定义一个接口
interface Inter
{
//定义一个方法
public abstract void method();
}
class Test
{
//补足代码
}
class InnerClassTest
{
public static void main(String[] args)
{
Test.function().method();
}
}
分析:
练习中的Test.function().method();语句
Test.function(): Test类中有一个静态方法function.
.method(): fanction这个方法运算后的返回值类型是一个对象,而且是Inter类型对象。 因为只有是Inter类型的对象才可以调用method方法。
所以通过分析Test.function().method()语句,补全的代码为
/*
内部类小练习
*/
//定义一个接口
interface Inter
{
//定义一个方法
public abstract void method();
}
class Test
{
//补足代码,通过匿名内部类
//静态方法function的返回值类型是个对象
static Inter function()
{
//返回的是Inter对象,但是Inter接口不能创建对象,所以要用匿名内部类
//创建Inter接口的子类
return new Inter()
{
//复写Inter接口中的方法
public void method()
{
System.out.println("内部类练习---内部类学完啦!");
}
};
}
}
class InnerClassTest
{
public static void main(String[] args)
{
Test.function().method();
}
}
程序运行结果
异常
因为java是面向对象的语言,所以就算是错误也被封装成了对象,就是我们接下来要学习的异常类。
异常类就是描述程序中可能出现的错误和问题而存在的。
流水线上的产品,前面一直都很顺利,到了某个环节发生了问题,产品就做不下去了,要人为的去检查哪儿出了错误,
对于不同的错误需要用不同的解决方案,不同的解决方案在异常中就可以体现。
异常就是程序在运行时出现的不正常的情况
异常的由来:
问题也是现实生活中具体的失误,也可以通过java的类的形式进行描述,并封装成对象。
其实就是java对不正产的情况进行描述后的对象体现(把问题封装成对象就是异常)
异常的好处:
1. 将问题进行封装
2. 将正常流程代码和问题处理相分离,方便阅读。
程序中可能出现的问题:
a. 用户输入错误导致的异常:如用户不正常使用程序,输入一些非法参数
b. 设备硬件等发生的错误:如硬盘损坏等
c. 物理限制:如存储空间不足等
d. 代码错误:在程序编写的方法可能不正确,返回错误参数等。
对问题的划分为两种:
1. 严重的问题
对于严重的问题通过Error类进行描述,对于Error一般不编写针对性的代码对其进行处理
2. 非严重的问题
对于非严重的问题通过Exception类进行描述,对于Exception可以使用针对性的处理方式进行处理。
无论Error或者Exception都具有一些共性内容,比如:不正常情况的信息或者引发的原因等
异常的体系:Throwable
|--Error
|--Exception
|--RuntimeException
1. Error:通常出现重大问题,如:运行的类不存在,或者内存溢出等。用Error处理
出现这种问题一般不进行针对性处理,直接修改程序
通常是不编写代码对其进行针对性处理的。
2. Exception:可以处理的问题,通过两种方式可以进行处理
a. 运行时出现的情况,可以通过 try catch finally代码块来处理
b. 通过throws再函数上声明(如果异常内throw异常那么函数必须声明)
小技巧:Exception和Error的子类名都是以父类名作为后缀的。
异常体系的特点
异常体系中所有类以及建立的对象都具备可抛性,也就是说可以被throw和throws关键字所操作,只有异常体系具备这个特点。
异常有两种
1. 编译时被检测的异常:该异常在编译时,如果没有处理(没有抛也没有try)编译失败。该异常被标识,则代表着可以被处理
2. 运行时异常(编译时不被检测):在编译时,不需要处理,编译器不检查。
该异常发生,建议不处理让程序停止,需要对代码进行修正。
异常的处理
Java提供了特有的语句对异常进行处理
try{
需要被检测的代码
}catch(异常类 变量){
处理异常的代码(处理方式)
}finally{
一定会执行的语句
}
try代码块有三种结合格式
1. try{
}catch( ){
}finally{
}
2. try{
}catch( ){
}
3. try{
}finally{
}
记住:catch是用于处理异常的,如果没有catch就代表一场没有被处理过,如果该异常是检测时异常,那么必须声明
注意:1. finally中放的是一定会执行的语句,一般存放关闭资源的语句,因为资源必须要被释。
2. 如果在一个功能中有必须要执行的语句,可以用try{}finally{}代码块来执行,
尽管没有异常需要处理也可以用这个,如果有必须要执行的语句就放在finally中
3. finally只在一种情况下不会执行,在前面的代码中出现System.exit(0)时,finally中的代码不会执行。
对捕获的异常对象进行常见方法操作
1. String getMessage():获取异常信息。
2. String toString():获取异常类名称,异常信息。
3. printStackTrace():获取异常名称,异常信息,还有异常出现的位置(因为返回值为void所以不需要打印语句打印,即可返回信息)
4. printStackTrace(PtintStream s):用该方法把异常信息保存在日志文件中,方便日后查看。
其实JVM默认的异常处理机制就是在调用printStackTrance()方法,打印异常在堆内存和栈内存中的跟踪信息。
建议:在进行catch处理时,catch中一定要定义具体的处理方式,不要简单的定义一句。
也不要就简单的写一句e.printStackTrace()输出语句。
throw(抛出)
throws Exception 在功能上通过throws的关键字声明了该功能有可能会出现问题
在函数行声明异常,便于提高安全性,让调用处进行处理,不处理便以失败。
throw和throws的用法
throw定义在函数内,用与抛出异常对象。
throws定义在函数上,用与抛出异常类,可以抛出多个,用逗号隔开。
当函数内容有throw抛出异常对象,并未进行try处理,必须要在函数上声明,否则编译失败。
throw单独存在时下面不要再写语句,因为他就是程序结束的标识
注意:RuntimeException除外,也就是,函数内如果抛出的是RuntimeException异常,函数上可以不用声明。
如果函数声明了异常,调用者需要进行处理,处理方式可抛可try。
调用者对抛出信息的处理:当在函数内部出现了throw抛出异常对象,那么就必须要给出对应的处理动作,
要么在内部try catch处理,要么在函数上声明,让调用者处理,一般情况下,函数内出现异常,函数上需要申明。
在功能上通过throws的关键字声明了该功能可能会出现异常类型。
Exception中有一个特殊的子类异常:RuntimeException运行时异常
如果在函数内抛出该异常,函数上可以不用声明,编译一样通过
如果在函数上声明该异常,调用者可以不用进行和处理,编译一样通过。
之所以不用在函数上声明,是因为不需要让调用者处理,当该异常发生,希望程序停止。
因为在运行时出现了无法继续运算的情况,希望停止程序后对代码进行修正。
对于异常两种分类的详细解读
1. 编译时被检测的异常
在java编译时期,它会去检测,如果方法中抛出了非RuntimeException异常或者其子类,如果在方法上没有标识,就视为安全隐患。
所以不标识就会编译失败,为什么要检测?
因为这个异常是可以处理的,要标识出去,让调用者处理,如果函数上标识了被检测异常,
调用者也必须有对应的处理方式,要么抛要么try。
2. 编译时不被检测的异常(运行时异常,RuntimeException以及其子类)
在函数内抛出异常,在函数上不用声明,因为凡是RuntimeException及其子类会判断异常对象是否intstanceof RuntimeException。
如果是,则编译通过,目的是让程序停止。
判断用哪种异常处理方式
在自定义问题时要分析,这个问题发生以后能否处理,如果不想能处理需要修正代码,就要继承RuntimeException
如果问题发生以后可以处理,处理完成后程序可以继续运行,那么就继承Exception。
自定义异常
因为项目中会出现特有的问题,而这些问题并未被Java所描述并封装对象,所以对于这些特有的问题可以按照Java对问题进行封装的思想,
将特有的问题进行自定义的异常封装。
定义类要么集成Exception要么继承RuntimeException,为的是让自定义类具备可抛性,让该类具备操作异常的共性方法。
当要自定义异常的信息时,可以使用父类已经定义好的功能,异常信息传递给父类的构造函数。
自定义异常按照java的面向对象思想,将程序中出现的特有问题进行封装。
当自定义了异常类继承Exception后,如果未在类中定义异常信息,
那么通过toString方法打印出来的结果就只有自定义的异常类名,不会显示异常信息。
如何定义异常信息呢?
因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时将异常信息传递给父类,通过super语句,
那么就可以直接通过getMessage()方法获取异常信息了
如下代码所示
class ZiDingYiException extends Exception
{
private String msg;
ZiDingYiException(String msg)
{
super(msg);//将会返回输入的信息
}
}
自定义异常时:如果该异常的发生,无法再继续进行运算的话,就让自定义异常继承RuntimeException
注意:自定义异常必须是自定义类有继承关系,一般是继承Exception
继承Exception的原因
异常体系有一个特点,因为异常和异常对象都需要被抛出,他们都具备可抛性
这个可抛型是Throwable这个体系的独有特点,只有这个体系中的类和对象才可以被throws和throw操作(有局限性)
异常处理的原则
1. 处理方式有两种:try或者throws
2. 调用到抛出异常的功能时,抛出几个就处理几个,会出现一个try对应多个catch的情况
3. 多个catch,父类的catch放在最下
4. catch内需要定义针对性的处理方式,不要简单的定义pringStackTrace(),或输出语句也不要不写。
当捕获到的异常,本功能处理不了时,可以继续在catch中抛出
如下面的程序
try
{
throw new AException
}
catch (AException)
{
throw e;
}
如果该异常处理不了,但并不属于该功能出现的异常,可以将异常转换后再抛出和功能相关的异常。
或者异常可以处理,但需要将异常产生后和本功能相关的问题提供出去,让调用者知道并处理。
也可以将捕获异常处理后,转换新的异常抛出。
这样就好比在给别人汇款时,如果ATM机出现故障,这时可以另外找地方去转,也可以告诉对方,汇款不成功。
转换成新的异常,代码如下:
try
{
throw new AException
}
catch (AException)
{
//对AException异常进行处理
throw new BException();
}
异常在子父类覆盖中的体现
1. 子类在覆盖父类方法时,如果父类的方法抛出异常,那么子类的覆盖方法,
如果需要抛出异常只能抛出父类的异常,或者该异常的子类。也可以不抛。
2. 如果父类方法抛出多个异常,那么子类在覆盖方法时,只能抛出父类异常的子类
3. 如果父类或者接口中的方法没有异常抛出,那么子类在覆盖方法时也不可抛出异常,
如果子类方法发生了异常,就必须要进行try的处理,绝对不能抛
异常注意事项
问题在内部被解决就不需要被声明
在子类覆盖父类时
1. 子类抛出的异常必须是父类的异常的子类或者子集
2. 如果付类或者接口没有异常抛出是,子类覆盖出现异常,只能try不能抛。
如下列程序所示
//AException继承Exception
class AException extends Exception
{
}
//BException继承AException
class BException extends AException
{
}
//CException继承Exception
class CException extends Exception
{
}
/*
以上代码的继承关系为
Exception
|--AException
|--BException
|--CException
*/
//定义一个父类
class Father
{
//定义一个方法,抛出A异常
void show() throws AException
{
}
}
//定义一个测试类
class Test
{
//定义一个方法参数接收父类对象
void function(Father f)
{
//通过try,catch代码块处理父类方法异常
try
{
//调用父类show方法
f.show();
}
//处理AException异常
catch (AException e)
{
}
}
}
//定义一个子类,继承父类
class Son extends Father
{
//复写父类中方法
void show() throws CException
{
//这样会编译失败,因为子类继承了父类,复写父类方法时抛出的异常应该是
//父类抛出的异常的子类,如果抛出BException就不会出错了。
}
}
异常练习
/*
异常练习
我去饭馆吃饭
描述我对菜进行的动作:
点菜
重新点
描述菜的问题
菜卖完了
菜太贵了,超出我的预算了
描述我
我看菜单
我开始选菜(选不是点,选是在脑子里想想自己吃什么)
我可能出现的问题
菜太贵了,我不要了
*/
//建立自定义异常类,想点的菜没有了
class NoHaveException extends Exception
{
NoHaveException(String str)
{
//利用super语句访问父类的构造函数。
super(str);
}
}
//自定义异常类,菜太贵了超出预算
class TooExpensiveException extends Exception
{
TooExpensiveException(String str)
{
super(str);
}
}
//自定义异常类,回家,无法继续吃饭了
class GoHomeException extends Exception
{
GoHomeException(String str)
{
super(str);
}
}
//创建一个饭馆类
class Restaurant
{
//定义标记
int start=2;
//点菜方法,可能会没有菜或者太贵
void order()throws NoHaveException,TooExpensiveException
{
if(start==2)
//抛出没有菜异常
throw new NoHaveException("我要的菜没有(小沈阳语调)");
else if(start==3)
//抛出菜太贵异常
throw new TooExpensiveException("唉呀妈呀,这菜太贵了");
//重新点菜
else
System.out.println("开始点菜了啊");
}
//重新点菜吧
void reordering()
{
start=1;
System.out.println("你家菜要什么什么没有,有的又太贵,我重新点");
}
}
class Me //我类
{
private String name;
private Restaurant res;
//对我进行初始化
Me(String name)
{
this.name=name;
//我对象已建立,饭馆对象也建立
res=new Restaurant();
}
//我开始跟服务员说我要什么菜,可能会发生我退菜,程序无法运行
public void speak()throws GoHomeException
{
//异常处理
try
{
//调用点菜方法
res.order();
}
//处理没有菜异常
catch (NoHaveException e)
{
//没有菜了就调用重新点菜方法。
res.reordering();
}
//处理菜太贵异常
catch (TooExpensiveException e)
{
//太贵了,前面的菜我也不要了
//调用喊退菜方法
back();
//抛出回家一场,并输出异常信息
throw new GoHomeException("这菜我不要了 太贵了也"+e.getMessage());
}
System.out.println(name+"吃饭");
}
void back()
{
System.out.println("退菜,我要退菜!!");
}
}
class ExceptionTest
{
public static void main(String[] args)
{
//创建我对象
Me m=new Me("萌萌的我");
//处理异常
try
{
//调用点菜方法
m.speak();
}
catch (GoHomeException e)
{
//输出异常名称,异常信息
System.out.println(e.toString());
System.out.println("不吃了,直接回家");
}
}
}
运行结果
正常情况
菜没有
菜太贵了
因为不太想和别人的一样,是临时想出来的例子,其实还是老师讲课的例子比较好,不过用这种轻松的方式来写博客。
我写的很开心,老师看着也会很放松吧,虽然可能逻辑有点儿不对,什么菜太贵点了都不吃什么的,
不过我已经很好的理解了异常,这种例子的小错误,希望老师见谅啦~
包
PPT上的定义
对类文件进行分类管理,给类提供多层命名空间,写在程序的第一行,类名的全称是包名.类名。包也是一种封装形式(包名所有字母小写)
我的理解
包就相当于一个文件夹,里面装的全都是类文件,在编写程序的过程中难免会有重名的情况,重名在中国更常见
因为太复杂的名字也不太好记,外国名就好一点,因为他们有中间名,还可能有好几个中间名。咳咳,话题扯远了。
为了对类进行分类的管理,就有了包的出现,在不同的包中可以有相同的类名,不会冲突。
写项目必须先写包,后写类,因为项目会有很多类组成,必须要进行有效的分区!
包的好处:包的出现可以让Java的运行文件和Java的源文件相分离
包的作用
1. 为避免多个类重名的情况,如果出现两个相同名字的类,可通过包将两者区分,从而避免冲突。
2. 对类文件进行分类管理,可以将相关的一些类放在同一个包中。
3. 给类提供多层命名空间。
使用包的规则
1. 包必须写在程序的第一行。
2. 类的全称:包名.类名。
3. 编译定义了包的程序文件时,在编译时要指定包的存储目录。
如:javac–d c:\mypack类名.java(-d:指定包所存放的目录 .:代表当前目录)
包与包之间的访问
1. 被访问的包中的类权限必须是public的。
2. protected:保护权限。不同包中的子类还可以直接访问父类中被protected修饰的成员。
3. 包与包之间可以使用的权限只有两种,public、protected,而protected修饰的只能只能给子类使用
下面我们来看四中权限下是否可以访问的表,权限从左至右,由大到小排序
类加了public之后类名和Java文件名必须保持一致,一个java文件里不能出现2个共有类或接口
import(导入)
为了简化书写使用import导入包中的类。
注意事项
1. 在导入包时,如果包中有很多类,可以使用通配符 *来替代包中的所有类。但是,建议不要使用通配符 * ,
因为将不需要使用的类导入后,会占用内存空间。所以在编写程序时,使用包中的哪些类,就导入哪些类。
2. 定义包名不要重复,可以使用url来完成定义,url是唯一的。
3. 导入的不同包中有相同类时,必须写类的全名来区分,否则将会报错。
Jar包
Jar包就是java的压缩包,方便项目的携带,方便于使用,只要在classpath设置jar路径即可,数据库驱动,SSH框架都是以jar包体现的。
jar.exe工具的命令
下面我们来看一个练习,创建两个包,并把它们存入jar包中
PackageDemo1程序
package package1;//定义包package1
//被访问的包中的类一定是public修饰的
public class PackageDemo1
{
public void show()
{
System.out.println("package.PackageDemo类中的show方法正在被调用");
}
}
PackageDemo2程序
package package1;//定义包package2
//导入package1包中的PackageDemo1类
import package1.PackageDemo1;
public class PackageDemo2
{
public static void main(String[] args)
{
//创建PackageDemo1的匿名对象,并调用PackageDemo1中的show方法
new PackageDemo1().show();
}
}
创建package1和package2包,并运行PackageDemo2程序
目录下产生的包
通过Dos命令行生成jar包
现在目录下就有了jar包和package1 package2
将两个包删除,只留下jar包,通过DOS命令行制定classpath,输出前面程序的结果
谢谢大家的观看~!
-----------android培训、java培训、java学习型技术博客、期待与您交流!---------