java基础知识总结3

一、内部类(局部内部类、成员内部类、匿名内部类)
1、定义

:内部类就是在类的内部定义一个类,它的分类有成员内部类、局部内部类、匿名内部类,
它可以定义在类中方法外,也可以定义在类中方法内,内部类的好处是可以访问外部类的私有成员,但外部类无法访问内部类的私有成员
通过使用内部类可以确保程序的结构清晰和代码精炼

编译后的内部类名称:InnerTest$A.class
2、分类

:成员内部类(静态成员内部类)、局部内部类、匿名内部类
a、成员内部类(非静态内部类):与外部类的属性和方法并列,成员内部类可以看作是外部类的实例变量
在内部类中访问实例变量:this.字段;
在内部类中访问外部类的实例变量:外部类名.this.字段
成员内部类中不能有静态字段或方法(final修饰的常量除外),因为Static在加载时就创建,此时内部类可能还没被实例化
在外部类的外部实例化对象:
Foo foo = new Foo();
Koo koo = foo.new Koo();
Foo.Koo koo = new Foo().new Koo();

b、静态内部类
静态内部类可以直接访问外部类的静态成员,不能访问外部类的实例成员,但可以通过外部类的实例(new 对象)来访问
静态内部类里面可以定义静态成员(其他内部类不可以)
静态内部类不可以使用private修饰
静态内部类的对象可以直接生成
Foo.Koo koo = new Foo().new Koo();
c、局部内部类
在方法中定义的内部类称为局部内部类,类似局部变量,不可以加修饰符public、protected、private,其范围为定义它的代码块
可以访问外部类的所有成员,还可以访问所在方法中的final修饰的参数和变量,但不能访问方法体中的局部变量
d、匿名内部类
匿名内部类没有类名,它必须继承一个类或者实现一个接口,并且不能显示的extends或implements关键字
匿名内部类不能有构造方法,因为它没有类名。可以通过new<父类名>的方法创建实例对象,匿名类的创建与定义同时进行
匿名内部类只能一次性的创建其对象
匿名内部类既可以在方法体中,也可以在参数列表中
注意:匿名内部类一定是在new的后面隐含实现一个接口或继承一个类,匿名内部类不是抽象类
匿名内部类必须实现他的父类抽象接口或接口里的所有的抽象方法
new 父类的构造器(实参列表)|实现接口(){
//类体
}
new Object(){
}
3、内部类的访问规则

:内部类可以直接访问外部类中的成员,包括私有
最近的外部类要访问内部类必须建立内部类对象new Inner().fumction()来访问内部类中的成员
如: Outer.Inner in = new Outer().new Inner();
in.function();
4、使用

:当描述事物时,事物的内部还有事物,该事物用内部类来描述,因为内部事物在使用外部事物的内容。
内部类定义在局部时,不能使用成员修饰符、static修饰,使用时需要new—
可以直接访问外部类中的成员,但不可访问它所在的局部中的变量,只能访问被final修饰的局部变量
5、代码分析

:例1:—-分类
public class Demo2 {
class B{//成员内部类——Demo2B.class
}
static class A{//静态成员内部类——Demo2A.class
}
void show(){
class C{//局部内部类——-Demo21C.class
}
}
public static void main(String[] args) {
class C{//局部内部类—-Demo22C.class
}
System.out.println();
}
}

例2:—–匿名内部类

1、 匿名内部类其实就是内部类的简写格式
2、 定义前题必须继承一个类或实现一个接口
3、 匿名内部类的格式: new 父类或接口(){定义子类的内容}
4、 匿名内部类定义的方法最好不要超过三个

public class Test{
public static void main(String[] agrs){
Test t=new Test(); //new了 一个Test对象
t.te(new A(){ //调用实例方法并且声明一个匿名内部类类作为一个参数传入
public void as(){
System.out.println(“我是实现了接口A的匿名类”);
}
}
);
}
void te(A a){ //实例方法
a.as();
}
}
interface A{ //声明了一个接口类
void as(); //抽象方法
}

例3:
class A{
void as(){
System.out.println(“我是内部类A”);
}
}
class B{
void bs(){
System.out.println(“我是内部类B”);
}
}
public class MultipleExtends {
private class C extends A{}
private class D extends B{}
public static void main(String[] args) {
MultipleExtends m=new MultipleExtends(); //声明一个外部类的对象
MultipleExtends.C c=m.new C(); //让外部类对象持有一个
MultipleExtends.D d=m.new D();//内部类对象的引用
c.as();
d.bs();
}
}

例4:—–内部类是可以被私有的
public class MemberClass {
private int i=10; //定义一个私有字段
private static int j=20;
public static void main(String[] args) {
MemberClass mc=new MemberClass();//new 一个外部类的对象
A a=mc.new A();//A a=new MemberClass().new A();//new 一个内部类的对象
a.as();//调用内部类的实例方法
}
private class A{
//static int j=6;
//int i=5; //定义一个内部类的实例字段
void as(){ //定义一个内部类的实例方法
System.out.println(“这里是内部类A”);
System.out.println(“调用外部类私有实例字段i:”+i);
System.out.print(“调用外部类私有静态字段j:”+j);
}
}
}

//———- java ———-
//这里是内部类A
//调用外部类私有实例字段i:10
//调用外部类私有静态字段j:20

例5:—-静态内部类
public class StaticClass {
private static int i=10; //定义一个私有静态字段
//private int j=7;
public static void main(String[] args) {
StaticClass sc=new StaticClass();//new 一个外部类的对象
A a=new StaticClass.A(); //new 一个静态内部类
a.as(); //调用静态内部类的实例方法
A.at //调用静态内部类的静态方法
}
static class A{
int i=5;
static at(){ //定义静态内部类的静态方法
System.out.println(“这里是静态内部类的静态方法”);
}
void as(){ //定义静态内部类的实例方法
System.out.println(“这里是内部类A”);
System.out.print(“调用外部类私有静态字段i:”+i);
}
}
}

例6:——局部内部类
public class InteriorClass {
private int i=5;
public static void main(String[] args) {
InteriorClass ic=new InteriorClass(); //new 一个对象
ic.as(); //调用实例方法
// B b=ic.new B();
}
void as(){
final int y=5; //常量
int u=1; //局部变量
class B{
void bs(){
System.out.println(“这里是内部类B”);
System.out.println(“调用i”+i);
System.out.println(“常量”+y);
}
}
new B().bs();
}
}

二、异常(try\catch\fainlly\throw\throws)

i、 异常的含义和分类

a)含义:异常是对问题的描述,将问题进行问题的封装
b)分类:java.lang.Object—–Throwable(java中所有错误和异常的超类)—–Error(无法通过代码来处理的错误)
|—————Exception(可处理的异常,并能恢复运行)
|—RuntimeException(运行时异常)—可以不捕获也可以不处理
|—-CheckedException(已检查时异常)—-必须捕获或处理不然编译失败—IOException\SQLException
标签(Marker)接口:既无字段又无方法—Cloneable/Serializable/EventListener

Error—-如:JVM硬件错误—-OutOfMemoryError—内存不足、不断的创建实例、StackOverflowError—递归导致的堆异常

2、异常分类(Throwable)
1、编译时被检测的异常
throws 需要处理
2、编译时不被检测的异常—运行时异常(RuntimeException或其子类)
函数内throw,函数外不需要声明,——–无法处理,需要修改代码

ii、 异常处理

a)RuntimeEception及其子类异常,不需要程序员处理,其后语句不编译
b)非运行时异常必须处理
c)Exeception中有一个特殊的子类异常RuntimeException,如果在方法内抛出该异常,方法上可以不用声明,编译可以通过;如果在方法上声明了该异常,调用者可以不用处理,编译可以通过。之所以不在函数声明,是因为不希望让使用者处理,当异常发生时,希望程序停止,程序员修正程序代码

异常的捕获和处理

第一种格式:
try{
//可能抛出异常的语句
}catch(异常类型 e){
//处理语句1
} catch(异常类型 e){
//处理语句2
}finally{
//一定执行的语句
}

finally只要用于异常处理,修饰异常块,无论异常是否处理都会执行
finally在return、throw前输出,不管return是在try还是catch中
finally定义一定执行的代码,通常用于关闭资源——如:数据库关闭连接

finally块在以下情况将不会被执行:
(1)finally块中发生了异常;
(2)程序所在线程死亡;
(3)在前面的代码中用了System.exit(0);
(4)关闭CPU。

第二种格式:
try{

}finally{

}

第三种格式:
try{

}catch(){

}

iii.在多个catch时只执行一个,自上而下遇到的第一个异常所对应的catch

如果没有对应的catch,则先执
行finally后在抛出,没有finally则直接抛出,定义多个catch可精确地定位异常。如果为子类的异常定
义了特殊的catch块,而父类的异常则放在另外一个catch块中,此时,必须满足以下规则:子类异常的处
理块必须在父类异常处理块的前面,否则会发生编译错误。所以,越特殊的异常越在前面处理,越普遍的
异常越在后面处理。这类似于制订防火墙的规则次序:较特殊的规则在前,较普通的规则在后。

throws——–声明方法抛出异常
1、说明:当不知道在当前代码中如何处理的时候,可以选择用throws将异常交给上层调用者处理
2、基本格式:
类型 方法名(形参列表)throws 异常列表(逗号隔开){
//代码
}

例:
//手工抛出异常实例
public class JavaThrow1{
public static void main(String[] args){
System.out.print(” Now”);
try{
System.out.print(” is”);
throw new NullPointerException();//直接抛出异常转到catch进行处理
//System.out.println(“This will not excute!”);//有throw这句执行不到
}catch (NullPointerException e){
System.out.print(” the”);
}
System.out.print(” time.\n”);
}
}

//自动抛异常
public class ExTest {
public static void main(String[] args){
String s=null;
try{
System.out.println(“0”);
int i=s.length();//自动抛异常–空指针异常
System.out.println(“2”);
}finally{
System.out.println(“1”);
}
}
}

例:——–throws
public class ExceptionTest4{
public static void p() throws ArithmeticException{
//间接抛出异常,自己并未处理,让方法的调用者来处理
int i;
i=4/0;//可能发生异常
System.out.println(“8”);
}
public static void main(String[] args){
try{
try{
p();//方法的直接调用调用者捕获异常处理
}catch(ArithmeticException e){
System.out.println(“Divider is zero !”);
}
}catch(RuntimeException e){
System.out.println(“4”);
}
}
}

v.java异常处理机制

答:程序出现想数组角标越界,空指针等错误时,JAVA就会用异常Throwable
来描述这些错误,Throwable继承了Object类,同时实现了Serializable接口,
根据出现的问题是否可以通过程序来解决。把Throwable分为Error错误和Exception异常,Exception根据编译时是否会被检
测分为运行时异常RuntimeException和已检测异常CheckedException。异常的处理方
式有两种,在发生异常的地方直接使用catch处理,或者将异常抛出给调用者,让调用者来处理。
 1、检查性异常——程序正确,但因为外在的环境条件不满足引发。例如:用
户错误及I/O问题—-程序试图打开一个并不存在的远程Socket端口。这不是程序
本身的逻辑错误,而很可能是远程机器名字错误(用户拼写错误)。对商用软件系统,
程序开发者必须考虑并处理这个问题。JAVA编译器强制要求处理这类异常,如果不
捕获这类异常,程序将不能被编译。
  2、运行期异常——这意味着程序存在bug,如数组越界,0被除,入参不满足规
范…..这类异常需要更改程序来避免,JAVA编译器强制要求处理这类异常。
  3、错误——一般很少见,也很难通过程序解决。它可能源于程序的bug,但一般
更可能源于环境问题,如内存耗尽。错误在程序中无须处理,而有运行环境处理。
三、 自定义异常

当jdk内置异常类型不能满足系统需求时,我们需要自定义异常,如:
public class MyExceptionTest {
public static void main(String[] args) {
MyExceptionTest mt = new MyExceptionTest();
mt.manager();
}

 public void registe(int num) throws MyException{
          if(num<0){
                   throw new MyException("人数为负数",3);
          }
          System.out.println(" 登记人数为:"+num);
 }

 public void manager(){
          try{
                   registe(-100);
          }catch (MyException e){
                   System.out.println("登记类型出错:"+e.getId());
                   e.printStackTrace();
          }       
          System.out.println(" 操作结束!");
 }

}
class MyException extends Exception{
private int id;
public MyException(){}
public MyException(String message,int id){
super(message);//调用父类的getMessage()
//父类中已经定义了getMessage()可以直接使用———–该方法为Exception继承Throwable的
this.id=id;
}
public int getId(){
return id;
}
}

自定义异常类必须要继承Exception/RuntimeException,如果该异常的发生无法再继续进行运算,就让它继承RuntimeException
继承的原因是为了让该类自定义类具备可抛型,让该类具备操作异常的共性方法
自定义异常:按照JAVA的OO思想,将程序中出现的特有问题进行封装
四、常见异常

IOException——————–输入输出异常
ClassNotFoundException——-找不到类异常
NumberFormatException———字符串到数字格式的异常
FileNotfoundException———–文件找不到异常
NoSuchMethodException—————请求方法异常

运行时异常:RuntimeException
SecurityException———–试图违反安全性异常
NullPointerException—-没有实例化却调用其属性和方法————–空指针异常
ArrayIndexOfBoundsException———数组越界异常
StringIndexOfBoundsException———字符串越界异常
ArithmeticException————–算数异常/除数为零异常
NullPointerException——-试图查找null异常

Main方法通常情况下不能把异常抛给JVM

Super a = new subclass();//向上转型—-
—overload看左边,override看右边
———————————–多态针对的是方法

异常的好处:1、将问题进行封装
2、将正常流程代码和问题代码进行分离,方便阅读

处理原则:
1、处理方式有:try或者throws
2、调用到抛出异常的功能时,抛出几个处理几个(一个try对应多个catch)
3、多个catch,父类的catch放到最后
4、Catch内,需要定义针对性的处理方式,不要简单的定义printStackTrace输出语句,也不要不写
5、当铺获到的异常,本功能处理不了时,可以继续在catch中抛出

6、 例:
try{
throw new AException();
}catch(AException e){
throw e;
}

7、如果异常在内部被处理(catch),外部则不需要抛出

基本格式:catch用来处理异常,如果该异常为检测时异常时,必须要处理或者抛出
异常继承时,子类只能抛出父类的异常或者该异常的子类/子集异常,也可以不抛出异常

异常的注意事项
1、在子父类覆盖时,
a)子类抛出的异常必须是父类异常的子类或子集
b)如果父类或接口没有异常抛出时,子类覆盖出现异常,只能try不能抛
c)如果父类中是RuntimeException时,子类可以不用抛出异常,反之,子类为RuntimeException异常,父类为其异常的子类或自己都可以编译通过

1、throw 与throws
throw 后跟异常对象(只能有一个),throws后跟异常类(多个时用逗号隔开);
位置:throw用在方法体中,代表手工抛异常,throws用在方法声明上,代表该方法可能发生异常

2、RuntimeException和CheckedException的区别
前者可以不在方法上声明也可以不处理,后者必须要处理或者抛出

猜你喜欢

转载自blog.csdn.net/yao302789/article/details/51004165