深刻理解Java编程的7个例子

Java编程理解
本文通过七个例子深入浅出地讲解了Java编程中的关键概念,包括环境配置、私有成员访问、多态性、匿名内部类、静态成员、引用变量以及异常处理。

转自:深刻理解Java编程的7个例子   佟强 2009年11月7日 http://blog.youkuaiyun.com/microtong

 

 1. 阅读下列代码回答问题(第一个Java程序,理解PATH和CLASSPATH,学会使用javac和java命令)

Code:
  1. view plaincopy to clipboardprint?   
  2. package cn.edu.uibe;      
  3. public class HelloWorld {      
  4.     public static void main(String[] args) {      
  5.         System.out.println("Hello World!");      
  6.     }      
  7. }     
  8. package cn.edu.uibe;   
  9. public class HelloWorld {   
  10.     public static void main(String[] args) {   
  11.         System.out.println("Hello World!");   
  12.     }   
  13. }  


 

问:

(1)上面代码所在的源文件的文件名是_______________?
(2)在DOS提示符下,当前目录为该源文件所在的目录,PATH环境变量已包含编译程序所在的路径,编译目标路径为“D:/classes”,编译命令行是_____________?
(3)为了让Java解释器能够找到编译后的类文件,需要如何设置环境变量___________?
(4)在正确设置了相关的环境变量之后,运行HelloWorld类的命令行是____________?


答案:

(1)HelloWorld.java,公共类必须定义在和类名同名的文件中,文件名区分大小写。

(2)javac -d D:/classes HelloWorld.java ,-d给出输出目录,javac会在D:/classes创建包的目录层次结构cn/edu/uibe/HelloWorld.class

(3)set CLASSPATH=.;D:/classses,CLASSSPATH给出Java寻找.class文件的多个路径,路径之间用分号分隔,“.”表示当前路径。

(4)java cn.edu.uibe.HelloWorld,注意需要给出包名,类名后面不要加“.class”。

2. 阅读下列代码回答问题(关于private的理解)

Code:
  1. view plaincopy to clipboardprint?   
  2. public class Light {      
  3.     private int brightness = 5;      
  4.     public void brighten(Light another){      
  5.         another.brightness++;      
  6.     }      
  7.     public static void main(String[] args) {      
  8.         Light light1 = new Light();      
  9.         Light light2 = new Light();      
  10.         light1.brighten(light2);      
  11.     }      
  12. }     
  13. public class Light {   
  14.  private int brightness = 5;   
  15.  public void brighten(Light another){   
  16.   another.brightness++;   
  17.  }   
  18.  public static void main(String[] args) {   
  19.   Light light1 = new Light();   
  20.   Light light2 = new Light();   
  21.   light1.brighten(light2);   
  22.  }   
  23. }  


 

问:上面代码Java编译器是否会给出错误提示?为什么?

答案:不会出现错误提示,private限制了私有变量只能被同一个类访问,但是没有限制同一个类的不同对象之间互相访问私有变量。实际上,private是在编译时进行检查,如果想限制同类对象之间互相访问,需要在动态运行时实现,开销较大,而且没有必要。

3. 阅读下列代码回答问题(关于多态性的理解)

Code:
  1. view plaincopy to clipboardprint?   
  2. class Base {      
  3.     int i=1;      
  4.     void f(){      
  5.         System.out.println("Base.f()");      
  6.     }      
  7.     void g(){      
  8.     f(); //会调用上面的f()方法吗?      
  9.     }      
  10. }      
  11. public class Derived extends Base { //继承了Base类      
  12.     int i=2; //Derived类的对象有1个i还是2个i呢? 答:2个      
  13.     void f(){ //覆盖override了f()方法      
  14.         System.out.println("Derived.f()");      
  15.     }      
  16.     public static void main(String[] args) {      
  17.         Derived d = new Derived(); //创建子类对象      
  18.         Base b = d; //没有创建对象,仅仅是父类引用指向了子类对象      
  19.         d.f(); //将会输出Derived.f()      
  20.         b.f(); //也会输出Derived.f(),方法具有多态性      
  21.         System.out.println(d.i); //输出的是2,d.i访问子类中定义的变量i      
  22.         System.out.println(b.i); //输出的是1,b.i访问的是父类中定义的变量i,成员变量是不会动态绑定而表现出多态性的。            
  23.         d.g(); //输出Derived.f()      
  24.         b.g(); //也输出Derived.f(),从父类中调用被覆盖的方法f(),也将调用到子类中更具体的方法。      
  25.     }      
  26. }     
  27. class Base {   
  28.     int i=1;   
  29.     void f(){   
  30.         System.out.println("Base.f()");   
  31.     }   
  32.     void g(){   
  33.  f(); //会调用上面的f()方法吗?   
  34.     }   
  35. }   
  36. public class Derived extends Base { //继承了Base类   
  37.     int i=2; //Derived类的对象有1个i还是2个i呢? 答:2个   
  38.     void f(){ //覆盖override了f()方法   
  39.         System.out.println("Derived.f()");   
  40.     }   
  41.     public static void main(String[] args) {   
  42.         Derived d = new Derived(); //创建子类对象   
  43.         Base b = d; //没有创建对象,仅仅是父类引用指向了子类对象   
  44.         d.f(); //将会输出Derived.f()   
  45.         b.f(); //也会输出Derived.f(),方法具有多态性   
  46.         System.out.println(d.i); //输出的是2,d.i访问子类中定义的变量i   
  47.         System.out.println(b.i); //输出的是1,b.i访问的是父类中定义的变量i,成员变量是不会动态绑定而表现出多态性的。     
  48.         d.g(); //输出Derived.f()   
  49.         b.g(); //也输出Derived.f(),从父类中调用被覆盖的方法f(),也将调用到子类中更具体的方法。   
  50.     }   
  51. }  


 

问: 写出上面代码的输出?

答案:参见代码注释,子类和父类中定义同名的变量时,仅仅是隐藏了,变量没有多态性;而对于覆盖的方法,Java表现出多态性,

会调用更具体的子类里面的方法,无论从哪里调用,无论使用什么引用类型调用。

4.阅读下列代码回答问题(关于匿名内部类的理解)

Code:
  1. view plaincopy to clipboardprint?   
  2. interface A {      
  3.     void f();      
  4. }      
  5. public class B {      
  6.     public void f(A a) {      
  7.     }      
  8.     public static void main(String[] args) {      
  9.         B b= new B();      
  10.         b.f(new A() {      
  11.             public void f() {      
  12.             }      
  13.         });      
  14.     }      
  15. }     
  16. interface A {   
  17.     void f();   
  18. }   
  19. public class B {   
  20.     public void f(A a) {   
  21.     }   
  22.     public static void main(String[] args) {   
  23.         B b= new B();   
  24.         b.f(new A() {   
  25.             public void f() {   
  26.             }   
  27.         });   
  28.     }   
  29. }  


 

问:请解释语句
b.f(new A() {
    public void f() {
    }
});
的含义与作用。

答案:

   这个语句在参数表中定义了一个匿名内部类,这个匿名内部类实现了接口A,实例化了一个匿名内部类的对象,并将这个对象传递给了接收接口A作为参数的方法f(A a)。需要注意的是接口A中的方法f()和类B中的方法f(A a)没有任何关系,是不同的方法。


5. 阅读下列代码回答问题(关于static的理解)

Code:
  1. view plaincopy to clipboardprint?   
  2. public class Static {      
  3.     static int i = 0;      
  4.     int j=0;      
  5.     public static void main(String[] args) {      
  6.         Static s1 = new Static();      
  7.         Static s2 = new Static();      
  8.         s1.i++;      
  9.         s2.i++;      
  10.         s1.j++;      
  11.         s2.j++;      
  12.         System.out.println(s1.i);      
  13.         System.out.println(s1.j);      
  14.         System.out.println(s2.i);      
  15.         System.out.println(s2.j);      
  16. }      
  17. }     
  18. public class Static {   
  19.  static int i = 0;   
  20.  int j=0;   
  21.  public static void main(String[] args) {   
  22.   Static s1 = new Static();   
  23.   Static s2 = new Static();   
  24.   s1.i++;   
  25.   s2.i++;   
  26.   s1.j++;   
  27.   s2.j++;   
  28.   System.out.println(s1.i);   
  29.   System.out.println(s1.j);   
  30.   System.out.println(s2.i);   
  31.   System.out.println(s2.j);   
  32. }   
  33. }  


 

问:写出上面代码的输出。

答案: 2 1 2 1,i是静态变量,类的所有实例共享同一个i,通常我们不通过引用变量访问静态变量,而是通过类名访问Static.i,注意Static是我们自己定义的类名,而小写的static是关键字,表示静态的,为类的所有实例共享的变量或方法。j是实例变量,每个对象具有不同的,属于其自身的一个变量j。

6. 阅读下列代码回答问题(关于引用变量的理解)

Code:
  1. view plaincopy to clipboardprint?   
  2. class Counter{      
  3.     int i=0;      
  4. }      
  5. public class Reference {      
  6.     public void plus(int i){      
  7.         i++; //不会改变传递进来的参数的值,Java传递基本类型时进行了值的拷贝      
  8.     }      
  9.     public void plus(Counter c){      
  10.         c.i++; //会改变,因为c是一个引用变量,相当于指针      
  11.     }      
  12.     public void create(Counter c){      
  13.         c = new Counter();       
  14.                   c.i++; //不会改变,因为c执行了另外一个新建的对象      
  15.     }         
  16.     public static void main(String[] args) {      
  17.         int i = 0;      
  18.         Reference r = new Reference();      
  19.         Counter c1 = new Counter();      
  20.         Counter c2 = new Counter();           
  21.         r.plus(i);      
  22.         r.plus(c1);      
  23.         r.create(c2);             
  24.         System.out.println(i);      
  25.         System.out.println(c1.i);      
  26.         System.out.println(c2.i);      
  27.     }      
  28. }     
  29. class Counter{   
  30.  int i=0;   
  31. }   
  32. public class Reference {   
  33.  public void plus(int i){   
  34.   i++; //不会改变传递进来的参数的值,Java传递基本类型时进行了值的拷贝   
  35.  }   
  36.  public void plus(Counter c){   
  37.   c.i++; //会改变,因为c是一个引用变量,相当于指针   
  38.  }   
  39.  public void create(Counter c){   
  40.   c = new Counter();    
  41.                   c.i++; //不会改变,因为c执行了另外一个新建的对象   
  42.  }    
  43.  public static void main(String[] args) {   
  44.   int i = 0;   
  45.   Reference r = new Reference();   
  46.   Counter c1 = new Counter();   
  47.   Counter c2 = new Counter();     
  48.   r.plus(i);   
  49.   r.plus(c1);   
  50.   r.create(c2);     
  51.   System.out.println(i);   
  52.   System.out.println(c1.i);   
  53.   System.out.println(c2.i);   
  54.  }   
  55. }  


 

问:上面代码输出是?

答案:参考代码注释,输出应该是:0 1 0

7. 阅读下列代码回答问题(关于异常的理解)

Code:
  1. view plaincopy to clipboardprint?   
  2. class MyException extends Exception{      
  3.     public MyException(String message){      
  4.         super(message);      
  5.     }      
  6. }      
  7. public class ExceptionDemo{      
  8.     public void f(int num) throws MyException {      
  9.         if(num<0){      
  10.             throw new MyException("参数不能为负数!");      
  11.         }      
  12.         System.out.println(num);      
  13.         }      
  14.     public void g(){      
  15.         try{      
  16.             f(1);      
  17.             f(3);      
  18.             f(0);      
  19.             f(-1);      
  20.             f(2);      
  21.             f(-5);      
  22.         }catch(MyException e){      
  23.             System.err.println(e.getMessage());      
  24.             return;//会立即返回吗?答:不会!      
  25.         }finally{      
  26.            System.out.println("无论什么时候!");         
  27.         }      
  28.     }      
  29.     public static void main(String[] args) {      
  30.         ExceptionDemo demo = new ExceptionDemo();      
  31.         demo.g();      
  32.     }      
  33. }     
  34. class MyException extends Exception{   
  35.  public MyException(String message){   
  36.   super(message);   
  37.  }   
  38. }   
  39. public class ExceptionDemo{   
  40.  public void f(int num) throws MyException {   
  41.   if(num<0){   
  42.    throw new MyException("参数不能为负数!");   
  43.   }   
  44.   System.out.println(num);   
  45.   }   
  46.  public void g(){   
  47.   try{   
  48.    f(1);   
  49.    f(3);   
  50.    f(0);   
  51.    f(-1);   
  52.    f(2);   
  53.    f(-5);   
  54.   }catch(MyException e){   
  55.    System.err.println(e.getMessage());   
  56.    return;//会立即返回吗?答:不会!   
  57.   }finally{   
  58.      System.out.println("无论什么时候!");    
  59.   }   
  60.  }   
  61.  public static void main(String[] args) {   
  62.   ExceptionDemo demo = new ExceptionDemo();   
  63.   demo.g();   
  64.  }   
  65. }  


 

问:上面代码输出是?

答案:输出是:1 3 0 参数不能为负数! 无论什么时候!

try语句块里面的一行代码抛出了异常,后续代码就不再执行了,而是转到catch开始匹配异常类型。finally语句块里面的代码始终会被执行,即使在catch语句块里面有行return语句也不会立即返回,Java确保finally语句块执行完函数才会返回。


本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/microtong/archive/2009/11/07/4782093.aspx

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/microtong/archive/2009/11/07/4782093.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值