1、内部类
访问规则:
内部类可以直接访问外部类中的成员,包括私有,之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this
外部类要访问内部类,必须建立内部类对象。
访问格式:当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中,可以直接建立内部类对象。
格式:外部类名.内部类名 变量名 = 外部类对象.内部类对象;
当内部类在成员位置上,就可以被成员修饰符所修饰
比如,private,将内部类在外部类中进行封装。
static,内部类就具备static的特性。当内部类被static修饰后,只能访问外部类中的static成员,不能访问非static成员,出现了访问局限。
在外部其他类中,如何直接访问static内部类。
注意:当内部类中定义了静态成员,该内部类必须是静态的。
当外部类中的静态方法访问内部类时,内部类也必须是静态的。
class Outer
{
int x=8;
int y=3;
static class Inter1//定义静态内部类
{
void function1()//定义非静态函数
{
}
static void function2()//定义静态函数
{
}
}
class Inter//内部类可以被private修饰
{
int y = 4;
void function()
{
int y = 5;
System.out.println(y);//y=5
System.out.println(this.y);// y = 4
System.out.println(Outer.this.y);//y=3
System.out.println(x);//内部类可以直接访问外部类成员,x前省略了Outer.this
}
}
void method()
{
Inter in = new Inter();//创建内部类对象,访问内部类方法
in.function();
}
}
class InterOuterDemo
{
public static void main(String[] args)
{
Outer ou = new Outer();
ou.mehod();
//直接访问内部类中的成员
Outer.Inter in = new Outer().new Inter()
//in.function
// 访问外部类中静态内部类中的非静态函数
new Outer.Inter1().function1();
// 访问外部类中静态内部类中的静态函数
Outer.Inter.function2();
}
}
2、当描述事物时,事物的内部还有事物,该事物用内部类来描述,因为内部事物在使用外部事物的内容
class Body
{
private class xinZang
{
}
public void show()
{
new xinZang();
}
}
3、匿名内部类,其实就是内部类的简写格式。定义匿名内部类的前提,内部类必须是继承一个类或者实现接口
注意: 只有内部类定义在成员位置上时,才能被private或static修饰。若定义在局部,则不能被static修饰。
内部类定义在局部时,不可以被成员修饰符所修饰;可以直接访问外部类中的成员,因为还持有外部类中的引用,但是不可以访问它所在的局部中的变量,只能被final修饰的局部变量
class Outer
{
int x= 3;
void method()//若void method(final int z),此时才可以被Inner访问
{
//方法内的内部类访问放发的局部变量
final int y = 5;//此时y必须被定义为final
class Inner
{
void function()
{
System.out.println(Outer.this.x);
System.out.println(y);//y被定义为final才能被访问,
System.out.println(z);
}
}
new Inner().function();
}
}
匿名内部类代码:一般情况
abstract class AbsDemo
{
abstract void show();
}
class Outer
{
int x= 3;
class Inner extends AbsDemo
{
void method()
{
System.out.println(x);
}
}
public void function()
{
new Inner().method();
}
}
改为匿名内部类
abstract class AbsDemo
{
abstract void show();
}
class Outer
{
int x= 3;
public void function()
{
//红色代码是一个整体,是一个对象,是类AbsDemo的子类对象,是上文绿色部分的简写。
new AbsDemo()
{
void show()
{
System.out.println(x);
}
void show1()//也可以定义其他方法,调用时.show()该为.show1(),但不能同时调用(.show().show1())
{
}
}
.show()//红色代码是对象,.show()表示调用方法show()
new AbsDemo()
{
void show()
{
System.out.println(x);
}
void show1()//也可以定义其他方法,调用时.show()该为.show1(),但不能同时调用(.show().show1())
{
}
}.show1()//调用方法show1()
/*另一种方法,给该对象起名字
AbsDemo abc = new AbsDemo()
{
void show()
{
System.out.println(x);
}
void show1()
{
}
}
abc.show();
abc.show1();//不可以,因为多态,abc只能调用父类中定义过的
*/
}
}
匿名内部类格式: new 父类 或者接口(){定义子类的内容}
其实;匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象。一般匿名内部类中定义的方法最好不要超过三个,因为匿名内部类就是为了简化代码的。
当用方法参数为接口类型时,可以定义一个匿名内部类传进方法。
public static void show(Inter in)
{
in.method();
}
public static void main(String[] args)
{
show(new Inter()
{
public void method()
{
System.out.println("method run");
}
});
]
另一个示例,创建object子类对象,用匿名内部类
class InnerTest
{
public static void main(String[] args)
{
new Object()
{
public void function()
{
System.out.println("dfdf");
}
}.function();
}
}
4、异常,就是程序在运行时出现不正常情况。
异常由来:问题也是现实生活中一个具体的事物,也可以通过java类的形式进行描述,并封装成对象。其实就是java对不正常情况进行描述后的对象体现。
问题的划分:
严重问题,java通过Error类进行描述。对于Error一般不编写针对性的代码对其进行处理 。
非严重问题,java通过Exception类进行描述。可以使用针对性的处理方式进行处理。
无论Error或者Exception都有一些共性内容,比如不正常情况的信息、引发原因等。将这些共性内容进行抽取,形成类Throwable,而类Error Exception是它的子类
5、异常处理,java提供了特有的语句进行处理,基本格式如下:
try
{
需要被检测的代码:
}
catch(异常类 变量)
{
处理一号仓的代码:处理方式
}
finally
{
一定会执行的语句
}
示例:
class Demo
{
int div(int a,int b)
{
return a/b;
}
}
class ExceptionDemo
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
System.out.println( d.div(3,0));//此时会出现异常
}
catch(Exception e)//创建对象接收问题对象
{
System.out.println("除以零");
System.out.println(e.getMassage());//获取异常信息
System.out.println(e.toString());//异常名称、异常信息
e.printStackTrace();//打印堆栈中的异常名称、信息、出现位置
//其实jvm默认的异常处理机制,就是在调用printStackTrace()打
//印异常在堆栈中的跟踪信息
}
System.out.println("over");
}
}
异常处理流程:
当d.div(3,0)时,出现了问题。
该问题所属的异常类将该问题封装成一个对象,new AritchmenticException()
将该问题丢给调用d.div(3,0)的函数,即main函数。
此时因为有try,就检测到了这个问题对象。
try将该问题对象丢给catch,catch中定义的Exception e 对象,用来接收这个问题对象。即Exception e = new ArithcmenticException();
catch接收完问题对象后,执行catch的语句进行处理。
6、throws关键字
class Demo
{
int div(int a,int b)
throws Exception//在功能上通过throws关键字声明
//了该功能有可能会出现问题
{
return a/b;
}
}
class ExceptionDemo
{
public static void main(String[] args)//
throws Exception 方式二抛异常
{
Demo d = new Demo();
//方式一:对异常进行捕捉
try
{
int x = d.div(4,1)
System.out.println( x);
}
cach(Exception e)
{
e.printStackTrace();
}
System.out.println("over");
}
}
throws 理解:当方法声明来了 throw Exception,表示该方法可能出现问题,而且强制要求后面应用到该方法的程序必须进行处理这个异常,通常有两种处理方法,一个是try cantch 进行捕捉,二是同样抛出异常,即throw Exception。若不处理则编译出错。不过一般情况不抛异常,而是进行捕捉
7、对多异常的处理(注意:程序中出现异常,但没处理,则程序终止)
声明异常时,建议声明更为具体的异常,这样处理的可以更具体。抛出几个异常,在try catch中就有几个catch,每个catch处理一个异常,更有针对性。(但是,可以写一个catch(Exception e),因为多态性,这里e可以接受一切异常,如果这样的话就不具备针对性,容易忽略一些不可预料的异常,如果一定要写则要放在所有catch的最后面);如果多个catch块中的异常出现继承关系,父类异常catch要放在最下面。
注意:建议在进行catch处理时,catch中一定要定义具体处理方式,不要简单定义句e.printStackTrace(),也不要简单的就书写一条输出语句。
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 ExceptionDemo
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
int x = d.div(4,1)
System.out.println( x);
}
cach(ArithmeticException e)
{
e.printStackTrace();
}
catch(ArrayIndexOutOfBoundsException e)
{
e.printStackTrace();
}
System.out.println("over");
}
}
8、自定义异常 ,因为项目中会出现一些特有的问题,而这些问题并未被java所描述并封装对象,所以对于这些特有问题可以按照java的对问题封装的思想,将特有的问题,进行自定义的异常封装。
当在函数内部出现了throw抛出异常对象,那么就必须给出对应的处理动作。一是在内部try catch 二是在函数上声明让调用者处理
一般情况下函数内出现异常,函数上需要声明。
因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时,将异常信息传递给父类通过super语句。那么就可以直接通过getMessage方法获取自定义的异常信息。
自定义异常:必须是自定义类继承Exception。
继承Exception原因:异常体系有一个特点,因为异常类和异常对象都需要被抛出。他们都具备可抛性,这个可抛性是Throwable这个体系的独有特点,只有这个体系中的类和对象才可以被throw和throws操作。
需求:在本程序中,对于除数是负数,也视为是错误的,那么就需要对这个问题进行自定义异常。
class FuShuException extends Exception
{
/*
因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时,将异常信息传递给父类通过super语句。那么就可以直接通过getMessage方法获取自定义的异常信息。
FuShuException(String msg)
{
super(msg);
}
*/
private String msg;
FuShuException(String msg)
{
this.msg = msg;
}
public String getMessage()//重写父类Exception中的方法getMessage
{
return msg;
}
}
class Demo
{
int div(int a ,int b) throws FuShuException//一般情况下函数内出现异常,函数上需要声明。
{
if(b<0)
{
throw new FuShuException();//手动通过throw抛出一个自定义异常对象
}
return a/b;
}
}
class ExceptionDemo
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
int x = d.div(4,1)
System.out.println( x);
}
cach(FuShuException e)
{
System.out.println("出现负数了");
}
System.out.println("over");
}
}
9、throws与throw的区别
一:throws使用在函数上,throw使用在函数内。
二:throws后面跟的是异常类,可以是多个,用逗号分开;throw后面跟的是异常对象
10、RunTimeException, Exception中一个非常特殊的子类异常,运行时异常。 如果在函数内抛出该异常,函数上可以不用声明,编译一样通过。
如果在函数上声明了该异常,调用者可以不用进行处理,编译一样通过。
之所以不用再函数上声明,是因为不需要让调用者处理。当该异常发生,希望程序停止,因为在运行时,出现了无法继续运算的情况,希望停止程序后,对代码进行修正。
class Person
{
public void checkName(String name)
{
// if("lise".equals(name) 该方法可以避免空指针异常
// if(name!=null&&name.equals("lise")
该方法可以避免空指针异常
if(name.equals("lise")/
/NullPointerException
System.out.println("yes");
else
System.out.println("no");
}
}
class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person();
p.checkName(
null);
}
}
自定义异常时,如果该异常的发生,无法再继续进行运算,就让自定义异常继承RunTimeException.
对于异常分两种:
一:编译时被检测的异常,非运行时异常,该异常必须被声明,需要调用者去处理,表示该异常可以被处理。
二:编译时不被检测的异常(运行时异常,RunTimeException,及其子类),该异常表示如果出现了异常,那么程序就无法进行下去了,必须修改代码。
注意:throw异常时,程序已经终止,因此throw后面的语句都执行不到。