内部类、异常处理
1.什么是内部类?内部类有几种?每一中内部类如何表示有那些些特征?
内部类
将一个类定义在另一个类里面,形成了包含关系。
内部类--被包含的类
外部类--包含内部类的类。
java中内部类的分类
1.1 成员内部类
格式:
public class 外部类{
public class 成员内部类{
}
}
在这里我们可以认为成员内部类就相当于外部类中的一个成员变量/实例方法。
----成员内部类中不能定义静态变量和静态方法。
----外部类的静态方法是不能访问成员内部类的。
----其他的类中如果想访问成员内部类中的变量和方法,就得先创建外部类对象。
成员内部类中的变量和方法的调用关系。
成员内部类的构造方法中可以访问成员内部类实例变量/成员内部类的实例方法,默认this.,可以省略this.
成员内部类的构造方法中可以访问成员内部类中其他的构造方法,通过new访问
成员内部类的实例方法中中可以访问成员内部类实例变量/成员内部类的实例方法,默认this.,可以省略this.
成员内部类的实例方法中中可以访问成员内部类构造方法,通过new访问
成员内部类中的方法访问外部类中的变量和方法
1.成员内部类的构造方法中可以访问外部类的实例变量/外部类的实例方法,默认外部类的类名.this,可以省略外部类的类名.this。
2. 成员内部类的构造方法中可以访问外部类的类变量/类方法,默认类名访问,也可以外部类的类名.this,可以省略类名/外部类的类名.this。
3.成员内部类的构造方法中可以访问外部类的构造方法,通过new访问。
4.成员内部类的实例方法中可以访问外部类的实例变量/外部类的实例方法,默认外部类的类名.this,可以省略外部类的类名.this。
5. 成员内部类的实例方法中可以访问外部类的类变量/类方法,默认类名访问,也可以外部类的类名.this,可以省略类名/外部类的类名.this。
6.成员内部类的实例方法中可以访问外部类的构造方法,通过new访问。
外部类中的方法访问成员内部类中的变量和方法
1外部类的构造方法/实例方法中可以访问成员内部类的构造方法【new】,实例变量/实例方法【对象调用】
2.外部类的类方法中不能访问成员内部类。
其他类中访问成员内部类中的变量和方法
其他中可以访问成员内部类,先创建外部类对象,然后在创建内部类对象
//外部类
public class TestClass3 {
//InnerClass--成员内部类
public class InnerClass{
//成员内部类的实例变量
public int innerid=1001;
//成员内部类的构造方法
public InnerClass(){
}
//成员内部类的实例方法
public void test1(){
}
}
}
1.2方法内部类---在这里我们可以认为方法内部类就相当于方法中的一个局部变量。
将java类定义在某一个方法中。
1.定义方法内部类的时候没有访问修饰符
2.方法内部类中不能出现类变量和类方法
3.方法内部类中的构造方法/实例方法,可以访问本方法中的局部变量,jdk8.0之前需要使用final修饰局部变量,包括参数
4.方法内部类中的构造方法/实例方法,可以访问外部类的实例变量/实例方法,默认外部类类名.this. , 可以省略外部类类名.this.
5.方法内部类中的构造方法/实例方法,可以访问外部类的类变量/类方法,默认外部类类名,也可以外部类类名.this. ,可以省略外部类类名/外部类类名.this.
6.定义该方法内部类的方法中可以访问这个方法内部类中的变量和方法,对象访问
7.外部类中的方法中是不能访问方法内部类的。【方法内部类当于方法中的一个局部变量】
import com.click369.test1.TestClass2.InnerClass;
public class TestClass {
//外部类的实例变量
public int testid=1000;
//外部类的类变量
public static String testname="lisi";
//外部类的构造方法
public TestClass(){
}
//外部类的实例方法
public void dox(){
//外部类中的方法中是不能访问方法内部类的。
//InnerClass inner=new InnerClass();
}
//外部类的类方法
public static void doxStatic(){
}
public void test1(double num2){
//test1方法中的局部变量
int num1=100;
//方法内部类---就相当于本方法中的局部变量
//A 定义方法内部的时候没有访问修饰符
//B 方法内部类中不能出现类变量和类方法
//C 方法内部类可以访问本方法中的局部变量,jdk8.0之前需要使用final修饰局部变量,包括参数
class InnerClass{
//方法内部类中的实例变量
public int innerid=1001;
//方法内部类中不能有类变量
//public static String innername="1001";
//方法内部类中的构造方法
public InnerClass(){
//方法内部类中的构造方法,可以访问本方法中的局部变量,jdk8.0之前需要使用final修饰局部变量,包括参数
System.out.println(num1);
System.out.println(num2);
//方法内部类中的构造方法,可以访问外部类的实例变量/实例方法,默认外部类类名.this. , 可以省略外部类类名.this.
System.out.println(TestClass.this.testid);
System.out.println(testid);
TestClass.this.dox();
dox();
//方法内部类中的构造方法,可以访问外部类的类变量/类方法,默认外部类类名 ,
//也可以外部类类名.this. ,可以省略外部类类名/外部类类名.this.
System.out.println(TestClass.testname);
System.out.println(TestClass.this.testname);
System.out.println(testname);
TestClass.doxStatic();
TestClass.this.doxStatic();
doxStatic();
}
//方法内部类中的实例方法
public void innerMethod(){
//方法内部类中的实例方法,可以访问本方法中的局部变量,jdk8.0之前需要使用final修饰局部变量,包括参数
System.out.println(num1);
System.out.println(num2);
//方法内部类中的实例方法,可以访问外部类的实例变量/实例方法,默认外部类类名.this. , 可以省略外部类类名.this.
System.out.println(TestClass.this.testid);
System.out.println(testid);
TestClass.this.dox();
dox();
//方法内部类中的实例方法,可以访问外部类的类变量/类方法,默认外部类类名 ,
//也可以外部类类名.this. ,可以省略外部类类名/外部类类名.this.
System.out.println(TestClass.testname);
System.out.println(TestClass.this.testname);
System.out.println(testname);
TestClass.doxStatic();
TestClass.this.doxStatic();
doxStatic();
}
//方法内部类中不能有类方法
//public static void innerStaticMethod(){}
}
//在定义该方法内部类的方法中,访问方法内部类中的变量和方法,只能对象访问
InnerClass inner=new InnerClass();
System.out.println(inner.innerid);
inner.innerMethod();
}
}
1.3 匿名内部类---类/抽象类/接口的子类
没有名字的内部类。
继承式的匿名内部类:
public class TestMain {
public static void main(String[] args) {
//调用MyClass中的实例方法
MyClass mc=new MyClass();
//当一个方法的参数是抽象类类型的时候,可以是传递子类对象、上转型对象
//子类对象、上转型对象在创建的时候需要独立构建一个子类。
//如果我偏不构建这个子类,还想调用这个参数是抽象类类型的方法,怎么办?????
//可以使用匿名内部类的结构完成对子类的构建,只是现在构建出来的这个子类没有名称
//所以才叫匿名内部类
mc.myTest(new TestClass(){
@Override
public void testAbstractMethod() {
System.out.println("重写抽象类中的抽象方法");
}
});
/*
* 匿名内部类
new TestClass(){
@Override
public void testAbstractMethod() {
}
}
上面的这种结构就是一个匿名内部类,它代表TestClass类的子类,只是这个子类没有名字
*/
//优点:可以有效的减少类的创建
//缺点:不利于程序的阅读和理解
}
}
接口式的匿名内部类:
public class TestMain {
public static void main(String[] args) {
//调用MyClass这个普通类中的实例方法
MyClass mc=new MyClass();
//当一个方法的参数为接口类型是,我们可以传递接口的子类对象/接口回调对象
//子类对象/接口回调对象,都需要构建一个独立的子类。
//如果我偏不构建这个子类,还想调用这个参数是接口类型的方法,怎么办?????
//可以使用匿名内部类的结构完成对接口子类的构建,只是现在构建出来的这个接口的子类没有名称
//所以才叫匿名内部类
mc.dox(new MyInterface() {
@Override
public void test1() {
System.out.println("重写接口的抽象方法");
}
});
/*
* new MyInterface() {
@Override
public void test1() {
System.out.println("重写接口的抽象方法");
}
}
上面的这种结构就是一个匿名内部类,它代表MyInterface接口的子类,只是这个接口子类没有名字
*/
//优点:可以有效的减少类的创建
//缺点:不利于程序的阅读和理解
}
}
1.4 静态嵌套类----就是成员内部类加上static修饰符。
1.4.1 静态嵌套类中的元素
1.实例变量 2.类变量 3.构造方法 4.实例方法 5.类方法
1.4.2 静态嵌套类中的方法访问其他的变量和方法
1.在静态嵌套类中构造方法和实例方法中访问静态嵌套类中的实例变量/实例方法,默认this.,可以省略this.
2.在静态嵌套类中构造方法和实例方法中访问静态嵌套类中的类变量/类方法,默认静态嵌套类类名.,也可以省略this.,可以省略静态嵌套类类名./this.
3.在静态嵌套类中类方法中不能访问静态嵌套类中的实例变量/实例方法。
4.在静态嵌套类中的类方法中访问静态嵌套类中的类变量/类方法,默认静态嵌套类类名.,可以省略静态嵌套类类名.
5.在静态嵌套类中的类方法中不能出现this.
6.在静态嵌套类中构造方法和实例方法/类方法可以访问构造方法,通过new访问。
1.4.3 静态嵌套类中访问外部类的变量和方法
1.静态嵌套类中的构造方法/实例方法/类方法可以访问外部类的实例变量/实例方法,只能通过外部类的对象访问
2.静态嵌套类中的构造方法/实例方法/类方法可以访问外部类的类变量/类方法,默认外部类的类名.,可以省略外部类的类名.
3.静态嵌套类中的构造方法/实例方法/类方法可以访问外部类的构造方法,通过new访问
1.4.4 外部类中访问静态嵌套类中的变量和方法
1.外部类中的构造方法/实例方法/类方法中可以访问静态嵌套类中的实例变量和实例方法,通过对象访问。
2.外部类中的构造方法/实例方法/类方法中可以访问静态嵌套类中的类变量和类方法,默认静态嵌套类的类名访问,也可以使用对象访问 ,以省略类名。
3.外部类中的构造方法/实例方法/类方法中可以访问静态嵌套类中的构造方法,通过new访问。
1.4.5 其他类中访问静态嵌套类中的变量和方法
1.在其他类中可以访问静态嵌套类中的实例变量和实例方法,通过对象访问。
2.在其他类中可以访问静态嵌套类中的类变量和类方法,默认静态嵌套类的类名访问,也可以使用对象访问 ,以省略类名。
3.在其他类中可以访问静态嵌套类中的构造方法,通过new访问。
注意:以上的访问是需要导包语句
import 包名.外部类类名.静态嵌套类的类名;
2.异常类的体系结构?Error和Exception的区别
任何人所写的程序都有可能出现异常,就像人会生病一样,程序出现异常是一种正常现象。
程序运行的时候可能出现的一些不正常的现象就是异常【Exception】。【可纠正,可避免】【感冒发烧】
程序运行的时候可能出现的一些不可回避的问题就是错误【Error】。【不可纠正】【癌症晚期】
java中的异常【Exception】和错误【Error】都是Throwable的子类。
public class Exception extends Throwable{}
public class Error extends Throwable{}
Throwable是java中异常处理类的顶级类。
3.运行时异常与非运行时异常
异常【Exception】又有2大类构成
运行时异常---程序编写的时候没有异常,在运行的时候才会出现的异常
非运行时异常---我们在编写程序的时候,就已经出现的异常。
4.如何处理异常?Try{}catch(){} throws throw finally
使用try{}catch(异常类型){}捕获处理异常。
public class TestMain {
public static void main(String[] args) {
int a=10;
int b=0;
int c=0;
c=a/b;
System.out.println("c=="+c);
}
}
运行结果:
当我们没有使用try{}catch(){}捕获处理异常的时候,默认java程序会将这个程序中的异常输出到控制台上。
public class TestMain {
public static void main(String[] args) {
try{
int a=10;
int b=0;
int c=a/b;
System.out.println("c=="+c);
}catch(Exception e){
System.out.println("处理异常的程序");
}
}
}
当我们使用try{}catch(){}捕获处理异常以后,那么程序出现异常以后会执行我们的异常处理程序。
public class TestMain {
public static void main(String[] args) {
try{
int a=10;
int b=0;
int c=a/b;
System.out.println("c=="+c);
}catch(Exception e){
//打印堆栈异常信息到控制台
e.printStackTrace();
}
}
}
当我们不想处理这个异常的时候,也可以通过try{}catch(){}将异常信息输出到控制台。
e.printStackTrace();//打印堆栈异常信息到控制台
结构:
try{
可能出现异常的java代码
}catch(异常类型){
捕获,处理异常
}
try{}catch(){}捕获处理异常的过程:
将可能出现异常的java代码使用try{}包围,当try{}中的java代码出现异常,程序就会立刻停止运行,转而执行try{}后面的catch(异常类型){}中的内容,catch块就是书写处理异常的代码。
try{}catch(异常类型){}中的catch中的异常类类型,往往是需要一个具体的异常类型。
例如上面的实例中输出的“java.lang.ArithmeticException”就是一个除数为0的具体异常类型
public class TestMain {
public static void main(String[] args) {
try{
int a=10;
int b=0;
int c=0;
c=a/b;
System.out.println("c=="+c);
}catch(ArithmeticException th){
System.out.println("catch块捕获处理异常");
//打印堆栈异常信息
th.printStackTrace();
}
}
}
但是我们往往不知道这种具体的异常类型是什么,我们就可以使用Exception或Throwable代替具体异常类型。
public class TestMain {
public static void main(String[] args) {
try{
int a=10;
int b=0;
int c=0;
c=a/b;
System.out.println("c=="+c);
}catch(Throwable th){
System.out.println("catch块捕获处理异常");
//打印堆栈异常信息
th.printStackTrace();
}
}
}
或者
public class TestMain {
public static void main(String[] args) {
try{
int a=10;
int b=0;
int c=0;
c=a/b;
System.out.println("c=="+c);
}catch(Exception e){
e.printStackTrace();
}
}
}
为什么可以使用Exception或Throwable代替具体异常类型?
Exception是所有具体异常类型的父类,Throwable是Exception的父类。
一个try{}后面可以出现多个catch(异常类型){}。当出现多个catch(异常类型){}的时候根据catch中的异常类型按照异常类型的级别从小到大排列。
区分异常类型的级别大小,看异常类型的继承关系
Throwable异常的顶级类,有一个子类Exception,Exception有很多的子类 ArithmeticException 是Exception众多子类中的一个。
由小到大的级别排列:
ArithmeticException Exception Throwable
Public class Throwable{
}
Public class Exception extends Throwable{
}
Public class ArithmeticException extends Exception {
}
例如:
public class TestMain {
public static void main(String[] args) {
try{
int a=10;
int b=0;
int c=0;
c=a/b;
System.out.println("c=="+c);
}catch(ArithmeticException e){
e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}catch(Throwable th){
th.printStackTrace();
}
}
}
finally{}块出现在最后一个catch块的后面,程序有没有异常都会被执行的部分。
public class TestMain {
public static void main(String[] args) {
try{
int a=10;
int b=1;
int c=0;
c=a/b;
System.out.println("c=="+c);
}catch(ArithmeticException e){
e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}catch(Throwable th){
th.printStackTrace();
}finally{
System.out.println("程序有没有异常都要执行的部分");
}
}
}
在方法定义部分,使用throws 异常类型,声明该方法抛出异常。谁调用这个方法谁就要
处理这个方法抛出的异常。什么位置调用,什么位置处理。
public class TestClass {
//在方法定义部分,使用throws 异常类型,声明该方法抛出异常。
public int getValue()throws Exception{
int a=10;
int b=0;
int c=0;
c=a/b;
return c;
}
}
public class TestMain {
public static void main(String[] args){
try{
//谁调用这个方法谁就要,处理这个方法抛出的异常。什么位置调用,什么位置处理。
TestClass tc=new TestClass();
tc.getValue();
}catch(Exception e){
e.printStackTrace();
}
//谁调用这个方法谁就要,处理这个方法抛出的异常。什么位置调用,什么位置处理。
TestClass tc1=new TestClass();
tc1.getValue();
}
}
public class TestMain {
public static void main(String[] args)throws Exception{
//谁调用这个方法谁就要,处理这个方法抛出的异常。什么位置调用,什么位置处理。
TestClass tc1=new TestClass();
tc1.getValue();
}
}
当程序出现异常以后,有两种做法
1.我们自己使用try{}catch(){}捕获处理异常
2.使用throws 声明异常从方法上抛出,谁使用这个带有异常的方法,谁就处理这个方法的异常。
5.常见的异常
NullPointerException 空指针异常
ClassNotFoundException 指定类不存在
NumberFormatException 字符串转换为数字异常
IndexOutOfBoundsException 数组下标越界异常
ClassCastException 数据类型转换异常
FileNotFoundException 文件未找到异常
NoSuchMethodException 方法不存在异常
IOException IO 异常
SocketException Socket 异常