您的位置:首页 > 编程语言 > Java开发

牛逼笔记:java面向对象三

2013-01-19 15:14 134 查看
 

1.1.           静态内部类&局部内部类

l        静态内部类

用static修饰一个内部类,则这个类就属于外部类本身,而不属于外部类的某个对象。用static修饰的成员属于类而不属于对象。外部类的上一级单元是包,所以不能使用static修饰。但是内部类可以

       class Outer

{

         private static int num = 31;

 

         static class Inner//
内部类。

         {

                   void show()

                   {

                            System.out.println("showrun..."+num);

                   }                

         }

         public void method()

         {

                   Inner in = new Inner();

                   in.show();

         }

}

 

classInnerClassDemo

{

         public static void main(String[] args)

         {

                   //如果内部类是静态的。相当于一个外部类

                   Outer.Inner in = newOuter.Inner();

                   in.show();

                   //如果内部类是静态的,成员是静态的。

                   Outer.Inner.function();          

         }

}

 

l        局部内部类

把一个类定义在方法里面这个类就是局部内部类。局部变量作用域只在方法区内有效,其他程序访问不到,所以不能用static修饰局部变量,包括局部类。

class LocalInnerClass

{

     public static voidmain(String[] args)

     {

         class Inner//定义局部内部类

         {

              int a;

         }

         class SubInnerextends //Inner定义局部内部类继承Inner

         {

              int b;

         }

              SubInner s =new SubInner();

              s.a = 5;

              s.b = 6;

              System.out.println(s.a+";"+s.b);

     }

}

编译后出现一下三个文件:同一个类中可能有2个以上同名的内部类(处于不同方法中),所有内部类有编号

LocalInnerClassr.class

LocalInnerClass$1SubInner.class

LocalInnerClass$1Inner.class

1.2.           匿名内部类

2.      
错误收集

1:编译或者运行是类名或者文件名写错误提示,文件不存在

 

2:非法字符(可能输入中文字符)

 

2:内部类不能有静态声明

 

省略慢慢收集吧

3.      
异常

l        就是不正常

 

3.1.           异常概述

Java中,我们用类的形式对不正常的情况进行了描述和封装,这个类就是异常类。异常问题很多,也就意味着描述的类比较多,将其共享向上抽取,形成了异常体系:Throwable。

l        一般不可处理的Error

特点:由jvm抛出的严重性问题。这种问题发生一般不针对性处理。直接修改程序。

l        可以处理的Exception

l        无论是eoor,还是exception,问题发生了就应该可以抛出,让调用者知道丙处理。该体系的特点就在于Throwable及其所有的子类都具有可抛性。Throw
&throws

class Demo

{

         public void method(int[] arr, intindex)     {

                   System.out.println(arr[index]);

         }      

}

class ExcepTest

{

         public static void main(String[] args)

         {

                   int[] arr = new int[5];

                   Demo d = new Demo();

                   d.method(arr,8);

         }

}

 

l         

3.2.           异常小例一:

class Demo

{

         publicint arrOut(int[] arr, int index)

         {

                   if(arr == null)

                   {

                            thrownew NullPointerException("数组引用为空啦!!");

                   }

                   if(index >= arr.length)

                   {

                            thrownew ArrayIndexOutOfBoundsException("数组角标越界啦");

                   }

                   if(index < 0)

                   {

                            throw newArrayIndexOutOfBoundsException("数组角标不能为负数啊");

                   }

                   returnarr[index];

         }      

 

         publicstatic void main(String[] args)

         {

                   int[]arr = new int[5];

                   Demod = new Demo();

                   //intnum = d.arrOut(null, 3);// throw new NullPointerException("数组引用为空啦!!");

                   //intnum = d.arrOut(arr, 6);// throw new ArrayIndexOutOfBoundsException("数组角标越界啦");

                   intnum = d.arrOut(arr, 4);//正常输出,顺序执行

                   System.out.println("num:" + num);

                   System.out.println("Over");

         }

试想下:在上面的例子中javaAPI中丙没有定义数组角标为负的异常,那么我们就需要按照java的异常思想,面向对象,将负数角标进行自定义描述,丙封装成对象,这种自定义的问题描述,就是自定义异常。

3.3.           异常的分类

1:编译时被检测的异常:只要是Exception和其子类都是的,除了特殊子类RuntimeException体系。这种问题一旦出现,希望就在编译时就进行检测,让这种问题有对应的处理方式。这样的问题都可以针对性的处理。

2:运行时异常:就是Exception中的RuntimeException和其子类。这种问题的发生,无法让功能继续执行了,更多是因为调用者的原因导致而成活引发了内部状态的改变导致的,那么这种问题一般不予处理,直接编译通过,在运行的时候,让调用者调用时的程序强制停止,让调用者对代码进行修正。class
FushuIndexExceptionextends Exception//如果异常继承Exception类,则必须在函数上声明否则编译失败,

//而继承就不用声明,编译可以直接通过

RuntimeException

{

         FushuIndexException()

         {}

         FushuIndexException(String msg)

         {

                   super(msg);//调用父类构造函数

         }

}

l        注意:如果让一个类成为异常类,必须要继承异常体系,因为还有成为异常体系的子类才具备可抛性,才可以使用2个关键字throw
和throws(死肉,死肉丝)

 

3.4.           throw VS throws

1:throws使用在函数上,而throw使用在函数内

2:throws抛出的是异常类,可以抛出多个,用逗号隔开。Throw抛出的是异常对象。

修改7.2的代码;

n        自定义的异常不能被上一级识别,所以用throws标示在函数上

n        调用可能发生异常的函数,需要处理,或者throws或者catch

n        Throws声明的目的是让高速调用者需要处理。

class FushuIndexException extends Exception

{

       FushuIndexException()

       {}

       FushuIndexException(Stringmsg)

       {

              super(msg);//调用父类构造函数

       }

}

class Demo

{

       publicint arrOut(int[] arr, int index)throws FushuIndexException//抛出的异常不能被识别,需要声明或捕捉

       {

              if (arr == null)

              {

                     thrownew NullPointerException("数组引用为空啦!!");

              }

              if(index >= arr.length)

              {

                     thrownew ArrayIndexOutOfBoundsException("数组角标越界啦");

              }

              if(index < 0)

              {

                     thrownew FushuIndexException("数组角标不能为负数啊");

              }

              returnarr[index];

       }    

 

       publicstatic void main(String[] args)throws FushuIndexException

       {

              int[]arr = new int[5];

              Demod = new Demo();

              //intnum = d.arrOut(null, 3);

              //intnum = d.arrOut(arr, 6);

              //intnum = d.arrOut(arr, 4);

              intnum = d.arrOut(arr, -4);

              System.out.println("num:" + num);

              System.out.println("Over");

       }

}

 

 

 

 

3.5.           异常处理机制

Java的异常处理处理机制可以让程具有良好的容错性,让程序序更加健壮。让程序出现异常时,系统会自动生成一个Exception对象来告知程序,从而实现将业务功能代码和错误处理代码分离,提供良好的可读性。

 

Java用try ..catch来处理异常,格式:

try
{业务代码
}
catch (异常类变量)//用于接收发生的异常对象
{异常处理代码
}
Finally//通常用于关闭资源
{一定会处理的代码
}
执行try里面的代码出现异常生成异常对象,这个对象被抛出throw,当java运行环境收到这个对象后,把这个对象交给catch处理,如果找不到catch块,则运行环境终止,java程序也终止。

n        如果try被执行一次则后面只能有一个catch被执行

n        多catch中,如果存在父类,则父类一定放在后面(先处理小异常)

n        抛异常了才try,没throws异常try是没用的

3.6.           什么时候try什么时候throw

public int arrOut(int[] arr, int index)//输出函数//声明

      
{     try

{

          
if(index < 0)

          
       throw new FushuIndexException("数组角标不能为负数啊");         

}

catch{}

             
returnarr[index];

      
}    

如果调用者传递一个负数角标,发生异常,我们需要try吗?我们try的话,arr还是没有值,在内部没有解决这个问题。这个问题是调用者的问题,他传值错误,那是他的问题,所以我们声明出去

 

public static void main(String[] args)  
{

             
int[]arr = new int[5];

             
Demod = new Demo();

try  
{

      
              intnum = d.arrOut(arr, -4);

             
       System.out.println("num: " +num);

}

catch(FuShuIndexException e)//处理要有针对性

{

System.out.println(“数组角标越界”)

}

             
System.out.println("Over");

      
}

在调用的时候又出现问题,我们能处理吗?我们的原则就是能处理就try处理不了就抛。

上面的d.arrOut是调用者,我们需要告诉调用者,

3.7.           访问异常信息

String

getMessage
()


  返回此  throwable 的详细消息字符串。

void

printStackTrace()


  将此 throwable 及其追踪输出至标准错误流。


publicstatic void main(String[] args)throws FushuIndexException

         {

                   int[] arr = new int[5];

                   Demo d = new Demo();                 

                   try

                   {

                            int num =d.arrOut(arr, -4);

                            System.out.println("num:" + num);

                   }

                   catch (FushuIndexException e)

                   {

                            System.out.println("message;" + e.getMessage());

                            System.out.println("message;" + e);//将对象变字符串打印,此处不是e的哈希值,异常有自己独特的方法

                            e.printStackTrace();//JVM默认的异常处理机制就是这个

                            System.out.println("catch....角标负数异常啦");

                   }

                  

                   System.out.println("Over");

         }

3.8.           异常处理原则

n        函数内容如果抛出需要检测的异常,那么函数上必须要声明,否则必须在函数内部trycatch捕捉否则编译时失败

n        如果调用了声明异常的函数,那么要么trycatch要么throws,否则编译失败

n        什么时候catch,什么时候throws?:功能内部可以解决用catch,解决不了用throws告诉调用者,有调用者处理

n        一个功能如果抛出了多个异常,那么调用时,就必须对应多个catch进行捕捉,内部有几个需要检测的异常,就抛几个异常,抛出几个异常就catch几个

n         

3.9.           try catch final组合特点

n        try catch finally

n        try catch(多个)当没有必要资源需要释放时,可以不用定义finally

n        try finally

void show()//没有声明就得try

 

{

Try{

throw new Exception();}

catch(Exception e){}

}

3.10.      异常处理中的Finally

voidshow()throws Exception

 

{

Try{

开启资源;

throw new Exception();}

finally{

关闭资源;}

}

 

主要用于回收资源,(如数据库连接,网络连接,磁盘文件等。)这些物力资源都必须显示回收。

除非在trycatch中调用了退出虚拟机的方法,否则,不管在try、catch中执行怎么样的代码,异常处理的finally都会被执行。

 

4.  
线程

l        一个程序执行时,内部可能包含了多个顺序执行流,每个顺序执行流就是一个线程

4.1.           进程与线程

进程:(直译:正在进行中的程序。)操作系统可以同时运行多个任务,一个任务通常就是一个程序,每个运行中的程序就是一个进程。

线程:就是进程中一个负责程序执行的控制单元(执行路径)。一个进程中可以多执行路径,成为多线程。

 

扩展:一个进程中至少有一个线程;

进程特点:
             
独立性:进程是系统中独立存在的实体,每一个进程都有自己的地址空间。
             
动态性:进程有自己的生命周期和不同的状态。
并发性:多个进程可以再当个处理器上并发执行,多个进程之间不影响。

4.2.           多线程的利与弊

每一个线程都有自己运行的内容。这个内容可以成为线程要执行的任务。开启多个线程是为了同时运行多部分代码。

多线程好处:解决了多部分代码同时运行的问题

多线程弊端:线程太多导致效率的降低。

Run方法:封装任务代码。

4.3.           JVM启动时的多线程

其实啊,JVM启动时候就启动了多个线程,至少有2个线程可以分析出来。

 

任何线程启动都有自己的任务,

1:执行mian函数的线程

             
该线程的任务代码都定义在main函数中。

创建线程的目的是为了新开启一条执行路径,来执行指定的代码和其他代码实现同时运行。而运行的指定代码就是这个执行路径的任务。

                  
jvm创建的主线程的任务都定义在了主函数main中。

                  
线程是需要任务的,Thread类用于描述线程。所以Thread类也是对任务的描述。而这个任务就通过Thread类中的run方法来体现。也就是说,run方法就是封装自定义线程运行任务的函数。                  

                  
run方法中定义就是线程要运行的任务代码。

                  
开启线程是为了运行指定代码,所以创建线程必须继承Thread类,并复写run方法。

                  
将运行的代码定义在run方法中即可。      

2:负责垃圾回收的线程。

             
该线程的任务代码都在垃圾回收器中呢,在底层呢

class Demo extends Object //继承object类

{

        
publicvoid finalize(){   //复写finalize方法

System.out.println("demofinalized");

        
}

}

class 
ThreadDemo

{

        
publicstatic void main(String[] args) {

                  
newDemo();

                  
newDemo();

                  
newDemo();

                  
System.gc();//上面new的对象,不定时回收,所以为了演示效果调用System的gc()函数,运行垃圾回收期

                  
System.out.println("HelloWorld!");

        
}

}

下面只是输出结果其一,也有可能hello World
在后面,也有可能 dome finalized在前面,也与可能demo
finalized只输出一次,因为回收线程可能还没有执行完毕,虚拟机就运行完了,之后会强制回收的。

 

4.4.           创建线程两种方式和区别

创建线程方式一:继承Thread类。  

       步骤:   
定义一个类,继承Thread类。

                    
覆盖Thread类中的run方法。

                    
直接创建Thread的子类对象,创建线程。

                    
调用start方法开启线程丙调用线程的任务run方法执行。

class Demo extends Thread//继承Thread类

{

        
privateString name;

        
publicDemo(String name)

        
{

                  
this.name= name;

        
}

        
publicvoid run()//复写Thread的run方法,开发过程中run方法中定义就是线程要运行的任务代码。

        
{

                  
for(int i = 0; i < 10 ; i++ )

                  
{      

                           
for(int j = 10; j < 50000 ; j++ )//为了看看效果,多加一个空体的循环,不至于进程太快执行完毕

                           
{}

                           
System.out.println(name+ "..." + i + "...name = " +Thread.currentThread().getName());                   

                  
}

        
}      

}

class SuiTest

{

        
publicstatic void main(String[] args)

        
{

                  
Threadt1 = new Thread();//创建线程

                  
Demod1 = new Demo("-d1-d1-");

                  
Demod2 = new Demo("-d2-");

                  
d1.start();//开启线程

                  
d2.start();

                  
System.out.println("main_over..."+ Thread.currentThread().getName());

        
}      

}

/*

可以通过Thread的getName获取线程的名称Thread-编号(从0开始)

Main就是主线程。

*/

运行结果:

4.5.           start方法和run方法区别

 

转载请注明出处http://blog.csdn.net/bondsui
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息