第十四天 Core Java Advance Language Features II

第十四天 Core Java Advance Language Features II
内部类,使用内部类使编程更有层次,结构更清晰,但一切能用内部类解决的问题,外部类都能解决,只是编码是否繁琐的问题。

内部类,是作为外部类的成员。

内部类,修饰符可以为private protected static

四种内部类

成员内部类   局部内部类   静态内部类   匿名内部类

1.成员内部类,可以作为外部类的成员。

既然作为成员,那么四种访问修饰符适用。
优点:1任意访问外部类私有成员(属性,方法)
            2 定义比private还要小的访问控制权限(对于外部类) 
            3 成员内部类,不能有静态属性。

public   class  Outer  {
    
private int index = 100;
    
    
/** *//** Creates a new instance of Outer */
    
public Outer() {
    }

    
    
class Inner
    
{
        
private int index = 50;
        
void print()
        
{
            
int index = 30;
            System.out.println(index);
//局部变量30
            System.out.println(this.index);//内部类当前对象的index
            System.out.println(Outer.this.index);//引用外部类对象index
        }

    }

    
    
public static void main(String[] args)
    
{
        Outer outer 
= new Outer();
        Outer.Inner oi 
= outer.new Inner();
        oi.print();
    }

    
}

成员内部类对象依附于外部类对象。

所以,如果一个外部类继承另外一个类的内部类,那么这个类的构造函数必须需要一个那个内部类的外部类对象作为参数传入,才能成功构造该类对象。

class  WithInner  {
  
class Inner {}
}

public   class  InheritInner  extends  WithInner.Inner  {
  
//! InheritInner() {} // Won't compile
  InheritInner(WithInner wi) {
    wi.
super();
  }

  
public static void main(String[] args) {
    WithInner wi 
= new WithInner();
    InheritInner ii 
= new InheritInner(wi);
  }

}


局部内部类

public   class  Outer  {
    
private int index = 100;
    
    
/** *//** Creates a new instance of Outer */
    
public Outer() {
    }


    
void fn(final int a)
    
{
        
final int b = 0;
        
class Inner
        
{
            
int index = 50;
            
void print()
            
{
                
int index = 30;
                System.out.println(
this.index);
                System.out.println(Outer.
this.index);
                System.out.println(a);
                System.out.println(b);
            }

        }

        Inner in 
= new Inner();
        in.print();
    }


    
public static void main(String[] args)
    
{
        Outer outer 
= new Outer();
        outer.fn(
10000);
    }
   
}

可以访问实例变量,通过外部类当前对象。Outer.this
可以使用局部变量,但这些变量必须是final的。

局部内部类前没有访问控制修饰符,因为作用域就是在方法内部,指定无意义。

局部内部类对于外部类是透明的。


静态内部类

public   class  Outer  {
    
private int index = 100;
    
    
private static int index_static = 100;

     
/** *//** Creates a new instance of Outer */
    
public Outer() {
    }


    
static class StaticInner{
        
private int index = 50;
        
void print()
        
{
            
int index = 30;
            System.out.print(index);
            System.out.print(
this.index);
            System.out.print(Outer.index_static);
        }

        
    }


    
public static void main(String[] args)
    
{
        Outer.StaticInner st 
= new Outer.StaticInner();
        st.print();

    }

    
}

静态内部类只能访问外部类的静态成员(属性,方法)
创建对象,不依赖于外部类对象,是一个顶级类。

Outer.Inner in = new Outer.Inner();
in.***();

内部类重要用途,接口配合内部类实现完全的C++多继承功能。

接口不能完全实现多继承,简单例子,就是如果一个机器人Robet,父类People,机器Machine。
class People{

public void run(){}//跑

}

interface Machine{

void run(){}//运行

}

子类的run方法无法实现。类与接口的命名冲突,需要借助内部类。

public   class  Robot  extends  People {
    
    
/** *//** Creates a new instance of Robot */
    
public Robot() {
    }

    
    
public void run(){
        System.out.println(
"机器人跑");
    }

    
    
class Heart implements Machine{
        
public void run()
        
{
            System.out.println(
"心脏跳动");
        }

    }

}


abstract   class  People {    
    
abstract public void run();    
}


interface  Machine {
    
void run();
}

r = new Robet();r.run();

Robet.Heart h = r.new Heart();

h.run();

匿名内部类*

public   class  OuterNoName  {
    
    
/** *//** Creates a new instance of OuterNoName */
    
public OuterNoName() {
    }

    
    
public OuterNoName(IA impl)
    
{
        impl.run();
    }

    
    
public static void main(String[] args)
    
{
        OuterNoName onn 
= new OuterNoName(new IA(){
                
public void run(){
                    System.out.println(
"匿名内部类");
                }
                
        }
);
    }

    
}


interface  IA {    
    
void run();
}


构造函数参数传入时,直接生成一个实现IA接口的匿名内部类的对象。调用run方法时,多态会找到这个不知道叫什么名字的类的覆盖方法。

实现接口或者类

1在new后面使用,隐含着实现接口或者类,父类类型。
2 其他遵循局部内部类的规则
3无构造函数。无名嘛

===============================================

Exception

java.lang.Throwable是java.lang.Error和java.lang.Exception的父类。

java.lang.Error是指底层的,低级的,严重的,不可恢复的错误,例如内存不足等。
程序一定会退出。

java.lang.Exception是程序员关注的重点,例外又分为RunTime Exception未检查例外和已检查例外。

未检查例外是由于程序的大意,没有相应的检查,而出的例外。此类异常是可以避免的。
此类问题应提前提供应对策略,是可能出现的错误提前应对。

例如除0,数组越界,强制类型转换错误ClassCastException,等。java.lang.RuntimeException的子类都是未检查错误,去查API。

所以是编程避免。


已检查例外是需要程序处理的。

两种方式:
1.方法throws Exception
2.
try{
...
}catch(Exception ex)
{
...
}
finally
{
...
}

第一种是一种消极的处理方式,第二种是一种积极的处理方式。

如果不处理,程序非正常退出,影响出现其他代码正常运行,尽管他们没有关系。

Java是在网络上传输字节码。所以不会让程序中出现永远运行不到的语句,就是不能有废话。不能存在unreachable statement。

public   class  TestException  {
    
    
/** *//** Creates a new instance of TestException */
    
public TestException() {
    }

    
    
public static void main(String[] args) throws Exception
    
{
        System.out.println(
"main1");
        System.out.println(
"main2");
        print();
        System.out.println(
"main3");
    }

    
    
public static void print() throws Exception{
        System.out.println(
"print1");
        System.out.println(
"print2");
        subPrint();
        System.out.println(
"print3");
    }

    
    
public static void subPrint() throws Exception{
        System.out.println(
"subprint1");
        System.out.println(
"subprint2");
        
throw new Exception();
        
//System.out.println("subprint3");        unreachable statement
    }

}

应用try...catch...finally处理异常,保证程序正常退出。

     public   static   void  main(String[] args)
    
{
        System.out.println(
"main1");
        System.out.println(
"main2");
        
try{
        print();
        }

        
catch(IOException e){}
        
catch(Exception ex){}
        
finally{
            System.out.println(
"Run me whatever!");
        }

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


catch可以有多个,但一个异常只能匹配一个,而且catch的Exception从上到下,是子类到父类的顺序,不可颠倒。

try块中,有语句可能运行不到,finally无论如何都会被执行,即使catch块中有return语句,除非有System.exit(0);不会走finally块。

finally块中,主要放置释放资源,断开网络连接的代码。

     public   static   void  main(String[] args)
    
{
        System.out.println(cal(
0));
        System.out.println(cal(
1));
        System.out.println(cal(
2));
    }

    
public   int  cal( int  n)
    
{
        
try{
            
int r = (int)(2/n);
            
return r;
        }

        
catch(Exception ex){return 1;}
        
finally{
            
if(n == 2return 0;
        }

    }

一定要执行finally块语句,所以传入参数为2时,try计算完1,不能马上执行return,而是执行finally,最后执行finally块中的return。


ex.getMessage() ------>Exception(String message),注意需要构造对象时采用有参构造方法
ex.printStackTrace(),打印堆栈信息,最早出现位置,途经哪个方法。

开发一般规律:

1.try范围控制确定
写程序,联动操作,如果第一件事与第二件事无关,不要放置于同一个try块中。
如果第一件事影响到第二件事,放在一起。

2.try...catch,这种积极的处理方式,放置于最有能力处理的地方,否则采用throws方式,将例外抛给调用者。

联想:一个人要办一件事,他需要一个中介来办理,那么他将材料给了代理人,代理将材料提交给执行机构,办理过程中,执行机构发现材料不全,告知代理人,代理是没有能力来处理这件事的,只得再告知办理人,由办理人再行办理。


自定义例外

class MyException extends Exception{
   public MyException(String message)
   {
      super(message);
   }
}

==>throw new MyException("");


覆盖方法时,覆盖方法的例外抛出类型和数量有限制,类型相等,或者是被覆盖方法例外类型的字类型,数量只能更少。

try必须和catch或者finally配套出现。任何代码块中都可以再次嵌套try...catch...finally。








 



你可能感兴趣的:(第十四天 Core Java Advance Language Features II)