您的位置:首页 > 编程语言 > Java开发

Java基础视频教程第09天_面向对象之内部类、异常1

2015-03-16 06:24 666 查看
一、面向对象——内部类访问规则
1、内部类概念:
将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类、嵌套类)。

2、访问特点:
A、内部类可以直接访问外部类中的成员,包括私有成员;(之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式是:外部类名.this.)
B、外部类要访问内部类中的成员必须要建立内部类的对象。

3、外部其他类访问格式:
当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中直接建立内部类对象。
格式:
外部类名.内部类名 变量名 = 外部类对象.内部类对象。例如: Outer.Inner in = new Outer().new Inner();

4、注意:
内部类可以被 private 修饰,因为内部类是外部类的成员。此时,将内部类封装在外部类中。

示例:
	class InnerClassDemo
{
public static void main(String[] args)
{
//调用内部类的方式一:
Outer out = new Outer();
out.method();

//调用内部类的方式二:
Outer.Inner in = new Outer().new Inner();
in.function();

//调用内部类的方式三:
new Outer().new Inner().function();
}
}
class Outer
{
private int x = 3;
//private class Inner //内部类可以被私有
class Inner
{
int x = 4;
void function()
{
int x = 6;
System.out.println("inner:x1="+x);//打印6
System.out.println("inner:x2="+this.x);//打印4
System.out.println("inner:x3="+Outer.this.x);//打印3
}
}
void method()
{
Inner in = new Inner();
in.function();
}
}

二、面向对象——静态内部类

1、概念:
内部类是外部类的成员时,可以被 static 修饰,此时内部类就是静态内部类。

2、特点:
内部类被 static 修饰后,就具备 static 的特性,只能直接访问外部类中的 static 成员。出现了访问局限。

3、访问规则:
A、在外部其他类中,直接访问 static 内部类中的非静态成员的方式:
new Outer.Inner().function();

B、在外部其他类中,直接访问 static 内部类中的静态成员的方式:
Outer.Inner.function();

4、注意:
A、当内部类中定义了静态成员,该内部类必须是 static 的。
B、当外部类中的静态方法访问内部类时,内部类也必须是 static 的。

示例:
[code] class InnerClassDemo
{
public static void main(String[] args)
{
Outer.Inner in = new Outer.Inner();//创建静态内部类规则;
in.function();
//new Outer.Inner().function();//当内部类静态时,访问内部类非静态方法的格式;
Outer.Inner.function();//当内部类方法静态时,可直接访问;
}
}
class Outer
{
private static int x = 3;
static class Inner
{ //当内部类中定义了静态成员,该内部类必须是静态的
static void function()
{
System.out.println("inner:x="+x);//x相当于out.x
}
}
public static void method()
{
new Inner().function();
}
}

三、面向对象——内部类定义原则

1、什么时候定义内部类?
当描述事物时,事物的内部还有事物,该事物用内部类来描述。因为内部事物在使用外部事物的内容。

示例:
class Body
{
private class Heart
{
}
public Heart show()
{
return new Heart();
}
}

四、面向对象——局部/匿名内部类

(1)局部内部类:
1、内部类不仅可以定义在外部类成员位置上,也可以定义在局部位置上。
补充:一般内部类不会被 public 修饰,内部接口除外。

2、局部内部类的特点:
A、可以直接访问外部类中的成员,因为还持有外部类中的引用;
B、局部内部类不可以被 private 和 static 修饰;
C、局部内部类中的内部成员也不可以被 private 和 static 修饰;
D、局部内部类只能访问被 final 修饰的局部变量;
示例:
class InnerClassDemo3
{
public static void main(String[] args)
{
Outer out = new Outer();
out.method(5);
out.method(6);
}
}

class Outer
{
int x = 3;
void method(final int z)
{
final int NUM = 4;
class Inner
{
void function()
{
//z++;//z 被final修饰,不能重新赋值。
System.out.println("x="+x);
System.out.println("NUM="+NUM);
System.out.println("z="+z);
}
}
new Inner().function();//建立对象提供访问
}
}

(2)匿名内部类:
1、匿名内部类是内部类的简写格式。

2、定义匿名内部类的前提:
内部类必须是继承一个类或者实现接口。

3、匿名内部类的格式:
new 父类或者接口(){定义子类内容,复写父类方法};

4、其实匿名内部类就是一个匿名子类对象,这个对象有具体内容。

5、匿名内部类中定义的方法一般不超过3个。

示例:
class InnerClassDemo4
{
public static void main(String[] args)
{
Outer out = new Outer();
out.function();
}
}
abstract class AbsDemo
{
abstract void method();
}
class Outer
{
int x = 4;
public void function()
{
AbsDemo d = new AbsDemo()
{
final int num = 9;
void method()
{
System.out.println("x="+x);//x=4
System.out.println("num="+num);//num=9
}
void show()
{
System.out.println("haha");
}
};
d.method();
//d.show();//编译失败,因为父类中没有show方法

//但是可以按如下方法调用
new AbsDemo()
{
void method()
{
System.out.println("method");
}
void show()
{
System.out.println("show");
}
}.show();
}
}

(3)练习一:根据以下代码补足Test类中的代码
/*
class InnerClassTest
{
public static void main(String[] args)
{
Test.function().method();
}
}
interface Tnter
{
public abstract void method();
}
class Test
{
//补足代码
}
*/
class  InnerClassTest
{
public static void main(String[] args)
{
Test.function().method();
//Test.function(): Test类中有一个静态的方法function;
//.method(): function这个方法运算后的结果的一个对象,而且是一个Inter类型的对象,该对象用来调用method();
}
}
interface Inter
{
public abstract void method();
}
class Test
{
/*
//方法一:非匿名,内部类
static class Inner implements Inter
{
public void method()
{
System.out.println("method run");
}
}
static Inter function()
{
return new Inner();
}
*/

//方法二:匿名内部类
static Inter function()
{
return new Inter()
{
public void method()
{
System.out.println("method run");
}
};
}
}

(4)练习二: 什么时候使用匿名内部类?例如:
interface Inter
{
void method();
}
class InnerClassTest2
{
public static void main(String[] args)
{
//调用show方法时使用匿名内部类的方式
show(new Inter()
{
public void method()
{
System.out.println("method show run");
}
});
}
public static void show(Inter in)
{
in.method();
}
}

(5)面试题:
class InnerTest
{
public static void main(String[] args)
{
new Object()//Object obj = new Object()
{
public void function(){}
}.function();//OK,子类直接调用
//obj.function();//编译失败,因为父类中没有function方法。
}
}

五、面向对象——异常概述

1、异常体系
Throwable
Error
通常出现重大问题:如运行的类不存在或者内存溢出等;
不编写针对代码对其处理。
Exception
在运行时出现的情况,可以通过 try catch finally

2、 Exception 和 Error 的子类名都是以父类名作为后缀。

3、理解:
异常:就是程序在运行时出现不正常情况。

异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述。并封装成对象。异常其实就是java对不正常情况进行描述后的对象体现。

对于问题的划分:两种:一种是严重的问题,一种非严重的问题。
对于严重的,java通过 Error 类进行描述。对于 Error 一般不编写针对性的代码对其进行处理。
对与非严重的,java通过 Exception 类进行描述。对于 Exception 可以使用针对性的处理方式进行处理。

无论 Error 或者 Exception 都具有一些共性内容。比如:不正常情况的信息,引发原因等。所以可以对其进行抽取出一个父类。

六、面向对象——异常 try - catch

1、异常处理:
java 提供了特有的语句处理异常:
try
{
需要被检测的代码;
}
catch ()
{
处理方式;
}
finally
{
一定会执行的语句;
}

2、常见的异常处理方法:
class Demo
{
public int div(int a, int b)
{
return a/b; //new ArithmeticException()
}
}

class ExceptionDemo
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
int x = d.div(4,0);//new ArithmeticException()
System.out.println("x="+x);
}
catch (Exception e)//Exception e = new ArithmeticException()
{
System.out.println(e.getMessage()); //  / by zero
System.out.println(e.toString());// 异常名称: 异常信息
e.printStackTrace();// 异常名称: 异常信息;异常出现的位置。//JVM默认异常处理方式。
}

System.out.println("over");
}
}

3、对捕获到的异常对象进行常见方法操作:
String getMessage();
String toString();
printStackTrace();

注意:
在输出语句中可以不用写 toString()方法,因为会自动调用。

七、面向对象——异常声明

1、如果程序运行过程中, try 中的代码不出现问题,则 catch 中的代码不会执行,而是继续向下运行。

2、在编写一个功能时,如果该功能有可能会出现异常;那么就必须在该功能上做一个标示,并通过 throws 关键字声明出该异常,以便调用者在调用该功能时知道该功能可能会出现的异常。

3、调用者对于接收到声明了有可能出现问题的程序时,就需要通过 try catch 处理,或者继续抛出。否则编译失败。
class Demo
{
int div(int a, int b)throws Exception //在功能上通过throws关键字声明了该功能有可能出现问题
{
return a/b;
}
}
class ExceptionDemo2
{
public static void main(String[] args) //throws Exception //或者继续抛出异常
{
Demo d = new Demo();

try //抛出异常时,尝试运行
{
int x = d.div(4,0);
System.out.println("x="+x);
}
catch (Exception e) //异常处理方式
{
System.out.println(e.toString());
}

System.out.println("over");
}
}

八、面向对象——多异常处理

1、声明异常时,建议声明更为具体的异常,这样可以处理得更具体。

2、处理原则:
A、对方声明几个异常,就对应有几个 catch 块进行针对性处理;不要定义多余的 catch 块。
B、如果多个 catch 块中的异常出现继承关系,父类异常 catch 块放在最下面。

3、在进行 catch 处理时, catch 中一定要定义具体的处理方式;不要定义简单的输出信息。
class Demo
{
int div(int a, int b)throws ArithmeticException , ArrayIndexOutOfBoundsException
{
int[] arr = new int[a];
System.out.println(arr[4]);
return a/b;
}
}
class ExceptionDemo3
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
int x = d.div(4,0);
System.out.println("x="+x);
}
catch (ArithmeticException e)
{
System.out.println(e.toString());
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println(e.toString());
}
/*
catch (Exception e)
{
System.out.println(e.toString());
}
*/

System.out.println("over");
}
}

九、面向对象——自定义异常

1、由来:
项目中会出现特有的问题,而这些问题并未被java所描述并封装成对象。所以对于这些特有问题,可以按照java对问题封装的思想,将特有的问题进行自定义的异常封装。

2、当在函数内部出现了 throw 抛出异常对象,那么就必须要给对应的处理动作。
要么在内部 try catch 处理。
要么在函数上声明让调用者处理。
一般情况下,函数内出现异常,函数上需要声明。 RuntimeException 除外。

3、如何定义异常信息呢?
因为父类中已经把异常信息的操作都完成了。
所以子类只要在构造时,将异常信息传递给父类通过 super 语句。
那么就可以直接通过 getMessage() 方法获取自定义的异常信息。

4、自定义异常,必须是自定义类继承 Exception 。

5、继承 Exception 的原因:
异常体系有一个特点:因为异常类和异常对象都被抛出。他们都具备可抛性。
这个可抛性是 Throwable 这个体系中独有特点。只有这个体系中的类和对象才可以被 throws 和 throw 操作。

====== java定义好的异常可以自动创建异常对象抛出,自定义异常需要手动创建异常对象并抛出。
====== 在编译时,先报告的是语法错误,异常问题最后报告。
class FuShuException extends Exception
{
//private String msg;
private int value;
FuShuException(String msg, int value)
{
super(msg);
//this.msg = msg;
this.value = value;
}
public int getValue()
{
return value;
}
/*
public String getMessage()
{
return msg;
}*/
}
class Demo
{
int div(int a, int b)throws FuShuException //函数内出现异常,函数上需要声明
{
if (b<0)
{
throw new FuShuException("/ by minus", b);//手动通过throw关键字抛出一个自定义异常对象。同时让程序跳转。
}
return a/b;
}
}

class ExceptionDemo4
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
int x = d.div(4,-2);
System.out.println("x="+x);
}
catch (FuShuException e)
{
System.out.println(e.toString());
System.out.println("除数: "+e.getValue());
}

System.out.println("over");
}
}

Throwable 以及 Exception 对message的定义思想体现:
class Throwable
{
private String message;
Throwable(String message)
{
this.message = message;
}
public String getMessage()
{
return message;
}
}
class Exception extends Throwable
{
Exception(String message)
{
super(message);
}
}

十、面向对象—— throw 和 throws 的区别

throws 和 throw 的区别:
throws 使用在函数上。
throw 使用在函数内。

throws 面跟的是异常类;可以跟多个。用逗号隔开。
throw 后跟的是异常对象。

十一、面向对象—— RuntimeException

1、 Exception 中有一个特殊的子类异常 RuntimeException 运行时异常。

2、 RuntimeException 异常的特点:
A、如果在函数内容抛出该异常,函数上可以不用声明,编译一样通过。
B、如果在函数上声明了该异常。调用者可以不用进行处理。编译一样通过;
原因:之所以不用在函数声明,是因为不需要让调用者处理。而应该在该异常发生时,希望程序停止。
因为在运行时,出现了无法继续运算的情况,希望停止程序后,对代码进行修正。

3、自定义异常时:如果该异常的发生,无法在继续进行运算,就让自定义异常继承 RuntimeException 。

4、对于异常分两种:
A,编译时被检测的异常。
B,编译时不被检测的异常(运行时异常: RuntimeException 及其子类)

5、 RuntimeException 子类举例:
RuntimeException
-ArithmeticException
-NullPointerException
-IndexOutOfBoundsException
-ArrayIndexOutOfBoundsException
-StringIndexOutOfBoundsException

代码一:
class FuShuException extends RuntimeException //希望发生该异常时,让程序停止
{
FuShuException(String msg)
{
super(msg);
}
}
class Demo
{
int div(int a, int b) //throws FuShuException, ArithmeticException 函数内抛出,函数上可以不用抛出
{
if(b<0)
throw new FuShuException("//by minus");
if(b==0)
throw new ArithmeticException("by zore ---");
return a/b;
}
}

class ExceptionDemo5
{
public static void main(String[] args) //throws FuShuException, ArithmeticException 接收了可能存在问题的该异常,可以不用处理
{
Demo d = new Demo();
int x = d.div(4,0);
System.out.println("x="+x);

System.out.println("over");
}
}

NullPointerException 举例:
class Person
{
private String name;
Person(String name)
{
this.name = name;
}
public boolean checkName(String name)
{
//if(name.equals("lisi"))
//当传入null时,会发生NullPointerException
if("lisi".equals(name))//修改技巧
//if(name!=null && name.equals("lisi"))
return true;
else
return false;
}
}
class Demo
{
public static void main(String[] args)
{
Person p = new Person("lisi");
boolean bl1 = p.checkName(null);
System.out.println(bl1);
boolean bl2 = p.checkName("lisi");
System.out.println(bl2);
}
}

十二、面向对象——异常练习

需求:
毕老师用电脑上课。
分析:
名词提炼法。

思考上课时,可能出现的异常:
电脑问题:
电脑蓝屏;
电脑冒烟

当冒烟发生后,出现讲课进度无法继续;就出现了新问题——课时计划无法完成。
代码:
class BlueException extends Exception
{ //定义异常类,该异常可处理
BlueException(String message)
{
super(message);
}
}
class MaoYanException extends Exception
{ //定义异常类,该异常不可以处理
MaoYanException(String message)
{
super(message);
}
}
class NoPlanException extends Exception
{
NoPlanException(String message)
{
super(message);
}
}

class Computer
{
private int state = 1;//1代表正常,2代表蓝屏,3代表冒烟
public void run(int num)throws BlueException,MaoYanException
{
state = num;
if(state==1)
System.out.println("computer run");
else if(state==2)
throw new BlueException("电脑蓝屏");
else if(state==3)
throw new MaoYanException("电脑冒烟");
else
System.out.println("传入非法值");
}
//重启电脑
public void reset()
{
state = 1;
System.out.println("computer reset");
}
}

class Teacher
{
private String name;
private Computer cmpt;
Teacher(String name)
{
this.name = name;
cmpt = new Computer();
}
public void prelect()throws NoPlanException
{
try
{
//设置电脑运行时可能出现的各种状况
cmpt.run(3);
}
catch (BlueException e)
{
System.out.println(e.getMessage());
cmpt.reset();
}
catch (MaoYanException e)
{
System.out.println(e.getMessage());
test();
throw new NoPlanException("no plan: "+e.getMessage());
}

System.out.println(name+": prelect");
}
public void test()
{
System.out.println("test");
}
}

class ExceptionTest
{
public static void main(String[] args)
{
Teacher t = new Teacher("bilaoshi");
try
{
t.prelect();
}
catch (NoPlanException e)
{
System.out.println(e.toString());
System.out.println("放假");
}
}
}

注意:
throw 单独存在时,下面不可以写语句, throw 是函数的结束标示,它一结束,下面的语句执行不到。
[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: