内部类、异常处理
1.什么是内部类?内部类有几种?每一中内部类如何表示有那些些特征?
(1)内部类
将一个类定义在另一个类里面,形成了包含关系。
内部类–被包含的类
外部类–包含内部类的类。
(2)java中内部类的分类
2.1成员内部类
格式:
public class 外部类{
public class 成员内部类{
}
}
在这里我们可以认为成员内部类就相当于外部类中的一个成员变量/实例方法。
-------成员内部类中不能定义静态变量和静态方法。
-------外部类的静态方法是不能访问成员内部类的。
-------其他的类中如果想访问成员内部类中的变量和方法,就得先创建外部类对象。
成员内部类中的变量和方法的调用关系。
成员内部类中的方法访问外部类中的变量和方法
-------成员内部类中不能定义静态变量和静态方法。
-------成员内部类的构造方法和实例方法,中可以访问成员内部类的实例变量/实例方法,默认this.,this.可以省略。
-------成员内部类的构造方法和实例方法,中可以访问外部类的实例变量/实例方法,默认外部类类名.this.,外部类类名.this.可以省略。
-------成员内部类的构造方法和实例方法,中可以访问外部类的类变量/类方法,默认外部类类名.,也可以外部类类名.this.,可以省略外部类类名./外部类类名.this.
例如:
package com.click369.test1;
//外部类
public class TestClass {
//外部类的实例变量
public int testid=1000;
//外部类的类变量
public static String testname="lisi";
//外部类的实例方法
public void dox(){}
//外部类的类方法
public static void doxStatic(){}
//InnerClass--成员内部类
public class InnerClass{
//成员内部类的实例变量
public int innerid=1001;
//A.成员内部类中不能定义静态变量[类变量]和静态方法。
//成员内部类的类变量
//public static String innername="inner";
//成员内部类的构造方法
public InnerClass(){
//成员内部类的构造方法中可以访问成员内部类的实例变量/实例方法,默认this.,this.可以省略。
//this---成员内部类----成员内部类对象
System.out.println(this.innerid);
System.out.println(innerid);
this.test1();
test1();
//成员内部类的构造方法中可以访问外部类的实例变量/实例方法,默认外部类类名.this.,外部类类名.this.可以省略。
//TestClass.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 test1(){
//成员内部类的实例方法中可以访问成员内部类的实例变量/实例方法,默认this.,this.可以省略。
//this---成员内部类----成员内部类对象
System.out.println(this.innerid);
System.out.println(innerid);
this.test1();
test1();
//成员内部类的实例方法中可以访问外部类的实例变量/实例方法,默认外部类类名.this.,外部类类名.this.可以省略。
//TestClass.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 testStatic1(){}
}
}
外部类中的方法访问成员内部类中的变量和方法
---------外部类的构造方法/实例方法中可以访问成员内部类的构造方法,实例变量/实例方法,只能对象调用
---------外部类的类方法中不能访问成员内部类。
例如
package com.click369.test1;
//外部类
public class TestClass2 {
//外部类的实例变量
public int testid=1000;
//外部类的类变量
public static String testname="lisi";
//外部类的构造方法
public TestClass2(){
//创建成员内部类的对象
InnerClass inner=new InnerClass();
System.out.println(inner.innerid);
inner.test1();
}
//外部类的实例方法
public void dox(){
//创建成员内部类的对象
InnerClass inner=new InnerClass();
System.out.println(inner.innerid);
inner.test1();
}
//外部类的类方法
public static void doxStatic(){
//创建成员内部类的对象
//InnerClass inner=new InnerClass();
//System.out.println(inner.innerid);
//inner.test1();
}
//InnerClass--成员内部类
public class InnerClass{
//成员内部类的实例变量
public int innerid=1001;
//成员内部类的构造方法
public InnerClass(){
}
//成员内部类的实例方法
public void test1(){
}
}
}
其他类中访问成员内部类中的变量和方法
--------其他类中可以访问成员内部类,先创建外部类对象,然后在创建内部类对象
例如:
package com.click369.test1;
//外部类
public class TestClass3 {
//InnerClass--成员内部类
public class InnerClass{
//成员内部类的实例变量
public int innerid=1001;
//成员内部类的构造方法
public InnerClass(){
}
//成员内部类的实例方法
public void test1(){
}
}
}
package com.click369.test1;
public class OtherClass {
public OtherClass(){
//TestClass3.InnerClass inner=new TestClass3().new InnerClass();
TestClass3 t3=new TestClass3();
TestClass3.InnerClass inner=t3.new InnerClass();
System.out.println(inner.innerid);
inner.test1();
}
public void testOther(){
TestClass3.InnerClass inner=new TestClass3().new InnerClass();
//TestClass3 t3=new TestClass3();
//TestClass3.InnerClass inner=t3.new InnerClass();
System.out.println(inner.innerid);
inner.test1();
}
public static void testStaticOther(){
TestClass3.InnerClass inner=new TestClass3().new InnerClass();
//TestClass3 t3=new TestClass3();
//TestClass3.InnerClass inner=t3.new InnerClass();
System.out.println(inner.innerid);
inner.test1();
}
}
2.2方法内部类
在这里我们可以认为方法内部类就相当于方法中的一个局部变量。
将java类定义在某一个方法中。
-------定义方法内部的时候没有访问修饰符
-------方法内部类中不能出现类变量和类方法
-------方法内部类中的构造方法/实例方法,可以访问本方法中的局部变量,jdk8.0之前需要使用final修饰局部变量,包括参数
-------方法内部类中的构造方法/实例方法,可以访问外部类的实例变量/实例方法,默认外部类类名.this. , 可以省略外部类类名.this.
-------方法内部类中的构造方法/实例方法,可以访问外部类的类变量/类方法,默认外部类类名,也可以外部类类名.this. ,可以省略外部类类名/外部类类名.this.
-------定义该方法内部类的方法中可以访问这个方法内部类中的变量和方法,对象访问
-------外部类中的方法中是不能访问方法内部类的。
例如:
package com.click369.test2;
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();
}
}
2.3匿名内部类—类/抽象类/接口的子类
没有名字的内部类
(1)继承式的匿名内部类
例如:
package com.click369.test3;
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类的子类,只是这个子类没有名字
优点:可以有效的减少类的创建
缺点:不利于程序的阅读和理解
(2)接口式的匿名内部类
例如:
package com.click369.test4;
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接口的子类,只是这个接口子类没有名字
优点:可以有效的减少类的创建
缺点:不利于程序的阅读和理解
2.4静态嵌套类----就是成员内部类加上static修饰符
例如:
package com.click369.test5;
//外部类
public class MyClass {
//静态嵌套类
public static class InnerClass{
//静态嵌套类中的实例变量
public int innerid=1001;
//静态嵌套类中的类变量
public static String innername="zhangsan";
//静态嵌套类中的构造方法
public InnerClass(){
//静态嵌套类中的构造方法中可以访问静态嵌套类中的实例变量/实例方法,默认this.,this.可以省略
System.out.println(this.innerid);
System.out.println(innerid);
this.test1();
test1();
//静态嵌套类中的构造方法中可以访问静态嵌套类中的类变量/类方法,
//默认类名.,也可以this.,可以省略类名./this.
System.out.println(InnerClass.innername);
System.out.println(this.innername);
System.out.println(innername);
InnerClass.testStatic();
this.testStatic();
testStatic();
}
//静态嵌套类中的实例方法
public void test1(){
//静态嵌套类中的实例方法中可以访问静态嵌套类中的实例变量/实例方法,默认this.,this.可以省略
System.out.println(this.innerid);
System.out.println(innerid);
this.test1();
test1();
//静态嵌套类中的实例方法中可以访问静态嵌套类中的类变量/类方法,
//默认类名.,也可以this.,可以省略类名./this.
System.out.println(InnerClass.innername);
System.out.println(this.innername);
System.out.println(innername);
InnerClass.testStatic();
this.testStatic();
testStatic();
}
静态嵌套类中的类方法
(1)静态嵌套类中的类方法中不能出现this
(2)静态嵌套类中的类方法中不能访问实例变量/实例方法
(3)静态嵌套类中的类方法中能访问类变量/类方法,默认类名.,可以省略类名.
例如:
//静态嵌套类中的类方法
public static void testStatic(){
//System.out.println(this.innerid);
//System.out.println(innerid);
//this.test1();
//test1();
System.out.println(InnerClass.innername);
//System.out.println(this.innername);
System.out.println(innername);
InnerClass.testStatic();
//this.testStatic();
testStatic();
}
}
}
package com.click369.test5;
//外部类
public class MyClass2 {
//外部类的实例变量
public int testid=1000;
//外部类的类变量
public static String testname="lisi";
//外部类的构造方法
public MyClass2(){}
//外部类的实例方法
public void dox(){}
//外部类的类方法
public static void doxStatic(){}
//静态嵌套类
public static class InnerClass{
//静态嵌套类中的实例变量
public int innerid=1001;
//静态嵌套类中的类变量
public static String innername="zhangsan";
//静态嵌套类中的构造方法
public InnerClass(){
//静态嵌套类中的构造方法能访问外部类的实例变量/实例方法,需要通过外部类对象访问
MyClass2 mc=new MyClass2();
//System.out.println(MyClass2.this.testid);
//System.out.println(this.testid);
//System.out.println(testid);
System.out.println(mc.testid);
//MyClass2.this.dox();
//this.dox();
//dox();
mc.dox();
//静态嵌套类中的构造方法能访问外部类的类变量/类方法,默认外部类的类名.,也可以对象访问,
//外部类的类名./对象,可以省略
//System.out.println(MyClass2.this.testname);
System.out.println(MyClass2.testname);
//System.out.println(this.testname);
System.out.println(testname);
System.out.println(mc.testname);
//MyClass2.this.doxStatic();
MyClass2.doxStatic();
//this.doxStatic();
doxStatic();
mc.doxStatic();
}
//静态嵌套类中的实例方法
public void test1(){
//静态嵌套类中的实例方法能访问外部类的实例变量/实例方法,需要通过外部类对象访问
MyClass2 mc=new MyClass2();
//System.out.println(MyClass2.this.testid);
//System.out.println(this.testid);
//System.out.println(testid);
System.out.println(mc.testid);
//MyClass2.this.dox();
//this.dox();
//dox();
mc.dox();
//静态嵌套类中的实例方法能访问外部类的类变量/类方法,默认外部类的类名.,也可以对象访问,
//外部类的类名./对象,可以省略
//System.out.println(MyClass2.this.testname);
System.out.println(MyClass2.testname);
//System.out.println(this.testname);
System.out.println(testname);
System.out.println(mc.testname);
//MyClass2.this.doxStatic();
MyClass2.doxStatic();
//this.doxStatic();
doxStatic();
mc.doxStatic();
}
//静态嵌套类中的类方法
public static void testStatic(){
//静态嵌套类中的类方法能访问外部类的实例变量/实例方法,需要通过外部类对象访问
MyClass2 mc=new MyClass2();
//System.out.println(MyClass2.this.testid);
//System.out.println(this.testid);
//System.out.println(testid);
System.out.println(mc.testid);
//MyClass2.this.dox();
//this.dox();
//dox();
mc.dox();
//静态嵌套类中的类方法能访问外部类的类变量/类方法,默认外部类的类名.,也可以对象访问,
//外部类的类名./对象,可以省略
//System.out.println(MyClass2.this.testname);
System.out.println(MyClass2.testname);
//System.out.println(this.testname);
System.out.println(testname);
System.out.println(mc.testname);
//MyClass2.this.doxStatic();
MyClass2.doxStatic();
//this.doxStatic();
doxStatic();
mc.doxStatic();
}
}
}
2.异常类的体系结构?Error和Exception的区别?
程序运行的时候可能出现的一些不正常的现象就是异常【Exception】。【可纠正,可避免】
程序运行的时候可能出现的一些不可回避的问题就是错误【Error】。【不可纠正】
public class Exception extends Throwable{}
public class Error extends Throwable{}
Throwable是java中异常处理类的顶级类。
3.运行时异常与非运行时异常?
异常【Exception】又有2大类构成
(1)运行时异常—程序编写的时候没有异常,在运行的时候才会出现的异常
(2)非运行时异常—我们在编写程序的时候,就已经出现的异常。
4.如何处理异常?Try{}catch(){} throws throw finally
(1)使用try{}catch(异常类型){}捕获处理异常
结构:
try{
可能出现异常的java代码
}catch(异常类型){
捕获,处理异常
}
try{}catch(){}捕获处理异常的过程:
将可能出现异常的java代码使用try{}包围,当try{}中的java代码出现异常,程序就会立刻停止运行,转而执行try{}后面的catch(异常类型){}中的内容,catch块就是书写处理异常的代码。
例如:
package com.click369.test1;
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();
}
}
}
或者
package com.click369.test1;
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的父类。
(2)finally{}块出现在最后一个catch块的后面,程序有没有异常都会被执行的部分
例如:
package com.click369.test1;
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("程序有没有异常都要执行的部分");
}
}
}
(3)在方法定义部分,使用throws 异常类型,声明该方法抛出异常。谁调用这个方法谁就要
处理这个方法抛出的异常。什么位置调用,什么位置处理。
例如:
package com.click369.test1;
public class TestClass {
//在方法定义部分,使用throws 异常类型,声明该方法抛出异常。
public int getValue()throws Exception{
int a=10;
int b=0;
int c=0;
c=a/b;
return c;
}
}
package com.click369.test1;
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();
}
}
package com.click369.test1;
public class TestMain {
public static void main(String[] args)throws Exception{
//谁调用这个方法谁就要,处理这个方法抛出的异常。什么位置调用,什么位置处理。
TestClass tc1=new TestClass();
tc1.getValue();
}
}
(4)手动引发异常throw 异常对象。
5.常见的异常?
算术异常类:ArithmeticExecption
空指针异常类:NullPointerException
类型强制转换异常:ClassCastException
数组负下标异常:NegativeArrayException
数组下标越界异常:ArrayIndexOutOfBoundsException
违背安全原则异常:SecturityException
文件已结束异常:EOFException
文件未找到异常:FileNotFoundException
字符串转换为数字异常:NumberFormatException
操作数据库异常:SQLException
输入输出异常:IOException
方法未找到异常:NoSuchMethodException
java.lang.AbstractMethodError
抽象方法错误。当应用试图调用抽象方法时抛出。
java.lang.AssertionError
断言错。用来指示一个断言失败的情况。
java.lang.ClassCircularityError
类循环依赖错误。在初始化一个类时,若检测到类之间循环依赖则抛出该异常。
java.lang.ClassFormatError
类格式错误。当Java虚拟机试图从一个文件中读取Java类,而检测到该文件的内容不符合类的有效格式时抛出。