Chinaunix首页 | 论坛 | 博客
  • 博客访问: 953221
  • 博文数量: 168
  • 博客积分: 3853
  • 博客等级: 中校
  • 技术积分: 1854
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-15 23:50
文章分类

全部博文(168)

文章存档

2014年(12)

2013年(46)

2012年(60)

2011年(11)

2010年(1)

2009年(17)

2008年(21)

我的朋友

分类: Java

2012-01-31 23:11:28

1,变量初始化顺序
Java代码  收藏代码
  1. package com.qdu.sun;  
  2. public class InitialOrderTest {  
  3. // 静态变量  
  4. public static String staticField = "静态变量";  
  5. // 变量  
  6. public String field = "变量";  
  7. // 静态初始化块  
  8. static {  
  9.         System.out.println(staticField);  
  10.         System.out.println("静态初始化块");  
  11. }  
  12. // 初始化块  
  13. {  
  14. System.out.println(field);  
  15. System.out.println("初始化块");  
  16. }  
  17. // 构造器  
  18. public InitialOrderTest() {  
  19. System.out.println("构造器");  
  20. }  
  21. public static void main(String[] args) {  
  22. new InitialOrderTest();  
  23. }  
  24. }  

执行结果;
静态变量
静态初始化块
变量
初始化块
构造器

但静态变量和静态块,变量和初始化块之间的顺序要看它们在类定义中的次序
Java代码  收藏代码
  1. package com.qdu.sun;  
  2. class Parent {  
  3.     // 静态变量  
  4.     public static String p_StaticField = "父类--静态变量";  
  5.     // 变量  
  6.     public String p_Field = "父类--变量";  
  7.     // 静态初始化块  
  8.     static {  
  9.     System.out.println(p_StaticField);  
  10.     System.out.println("父类--静态初始化块");  
  11.     }  
  12.     // 初始化块  
  13.     {  
  14.     System.out.println(p_Field);  
  15.     System.out.println("父类--初始化块");  
  16.     }  
  17.     // 构造器  
  18.     public Parent() {  
  19.     System.out.println("父类--构造器");  
  20.     }  
  21.     }  
  22.   
  23. public class SubClass extends Parent {  
  24. // 静态变量  
  25. public static String s_StaticField = "子类--静态变量";  
  26. // 变量  
  27. public String s_Field = "子类--变量";  
  28. // 静态初始化块  
  29. static {  
  30. System.out.println(s_StaticField);  
  31. System.out.println("子类--静态初始化块");  
  32. }  
  33. // 初始化块  
  34. {  
  35. System.out.println(s_Field);  
  36. System.out.println("子类--初始化块");  
  37. }  
  38. // 构造器  
  39. public SubClass() {  
  40. System.out.println("子类--构造器");  
  41. }  
  42. // 程序入口  
  43. public static void main(String[] args) {  
  44. new SubClass();  
  45. }  
  46. }  

执行结果:
父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块
父类--变量
父类--初始化块
父类--构造器
子类--变量
子类--初始化块
子类--构造器

2,String对象package com.qdu.sun;
Java代码  收藏代码
  1. public class StringStaticTest {  
  2. // 常量A  
  3. public static final String A;  
  4. // 常量B  
  5. public static final String B;  
  6.   
  7.   
  8. public static final String C = "AB";  
  9. //常量B  
  10. public static final String D="CD";  
  11.   
  12. static {  
  13. A = "ab";  
  14. B = "cd";  
  15. }  
  16.   
  17. public static void main(String[] args) {  
  18. // 将两个常量用+连接对s进行初始化  
  19.       
  20. String s = A + B;  
  21. String s2 = C + D;  
  22. String t = "abcd";  
  23. String t2 = "ABCD";  
  24. if (s == t) {  
  25. System.out.println("s等于t,它们是同一个对象");  
  26. else {  
  27. System.out.println("s不等于t,它们不是同一个对象");  
  28. }  
  29.   
  30. if (s2 == t2) {  
  31.     System.out.println("s2等于t2,它们是同一个对象");  
  32.     } else {  
  33.     System.out.println("s2不等于t2,它们不是同一个对象");  
  34.     }  
  35. }  
  36. }  

执行结果:
s不等于t,它们不是同一个对象(虽然A,B是final的,但不知何时赋初值,相当于变量)
s2等于t2,它们是同一个对象(因为C,D是final的,并有初值,编译时就确定了不会变的)
Java代码  收藏代码
  1. package com.qdu.sun;  
  2.   
  3. public class StringTest {  
  4.     public static void main(String[] args) {  
  5.   
  6.         String a = "ab";// 创建了一个对象,并加入字符串池中  
  7.         System.out.println("String a = \"ab\";");  
  8.         String b = "cd";// 创建了一个对象,并加入字符串池中  
  9.         System.out.println("String b = \"cd\";");  
  10.         String c = "abcd";// 创建了一个对象,并加入字符串池中  
  11.         String d = "ab" + "cd";  
  12.         // 如果d和c指向了同一个对象,则说明d也被加入了字符串池  
  13.         if (d == c) {  
  14.             System.out.println("\"ab\"+\"cd\" 创建的对象 \"加入了\" 字符串池中");  
  15.         }  
  16.         // 如果d和c没有指向了同一个对象,则说明d没有被加入字符串池  
  17.         else {  
  18.             System.out.println("\"ab\"+\"cd\" 创建的对象 \"没加入\" 字符串池中");  
  19.         }  
  20.         String e = a + "cd";  
  21.         // 如果e和c指向了同一个对象,则说明e也被加入了字符串池  
  22.         if (e == c) {  
  23.             System.out.println(" a +\"cd\" 创建的对象 \"加入了\" 字符串池中");  
  24.         }  
  25.         // 如果e和c没有指向了同一个对象,则说明e没有被加入字符串池  
  26.         else {  
  27.             System.out.println(" a +\"cd\" 创建的对象 \"没加入\" 字符串池中");  
  28.         }  
  29.         String f = "ab" + b;  
  30.         // 如果f和c指向了同一个对象,则说明f也被加入了字符串池  
  31.         if (f == c) {  
  32.             System.out.println("\"ab\"+ b 创建的对象 \"加入了\" 字符串池中");  
  33.         }  
  34.         // 如果f和c没有指向了同一个对象,则说明f没有被加入字符串池  
  35.         else {  
  36.             System.out.println("\"ab\"+ b 创建的对象 \"没加入\" 字符串池中");  
  37.         }  
  38.         String g = a + b;  
  39.         // 如果g和c指向了同一个对象,则说明g也被加入了字符串池  
  40.         if (g == c) {  
  41.             System.out.println(" a + b 创建的对象 \"加入了\" 字符串池中");  
  42.         }  
  43.         // 如果g和c没有指向了同一个对象,则说明g没有被加入字符串池  
  44.         else {  
  45.             System.out.println(" a + b 创建的对象 \"没加入\" 字符串池中");  
  46.         }  
  47.     }  
  48. }  

执行结果:
String a = "ab";
String b = "cd";
"ab"+"cd" 创建的对象 "加入了" 字符串池中
a +"cd" 创建的对象 "没加入" 字符串池中
"ab"+ b 创建的对象 "没加入" 字符串池中
a + b 创建的对象 "没加入" 字符串池中


3,变量覆盖
Java代码  收藏代码
  1. package variableOverride;  
  2.   
  3. class ParentClass {  
  4.     public int i = 10;  
  5. }  
  6.   
  7. public class SubClass extends ParentClass {  
  8.     public int i = 30;  
  9.   
  10.     public static void main(String[] args) {  
  11.         ParentClass parentClass = new SubClass();  
  12.         SubClass subClass = new SubClass();  
  13.         System.out.println(parentClass.i + subClass.i); // 40  
  14.     }  
  15. }  

这个问题虽然简单,但是情况却比较复杂。因为我们不仅要考虑变量、静态变量和常量三种
情况,还要考虑private、friendly(即不加访问修饰符)、protected和public四种访问权限下对属性的不同影响。


Java代码  收藏代码
  1. package variableOverride;  
  2. class ParentClass {  
  3.     private String privateField = "父类变量--private";  
  4.     /* friendly */String friendlyField = "父类变量--friendly";  
  5.     protected String protectedField = "父类变量--protected";  
  6.     public String publicField = "父类变量--public";  
  7.     // private的变量无法直接访问,因此我们给他增加了一个访问方法  
  8.     public String getPrivateFieldValue() {  
  9.     return privateField;  
  10.     }  
  11.     }  
  12. public class SubClass extends ParentClass {  
  13.     private String privateField = "子类变量--private";  
  14.     /* friendly */String friendlyField = "子类变量--friendly";  
  15.     protected String protectedField = "子类变量--protected";  
  16.     public String publicField = "子类变量--public";  
  17.   
  18.     // private的变量无法直接访问,因此我们给他增加了一个访问方法  
  19.     public String getPrivateFieldValue() {  
  20.         return privateField;  
  21.     }  
  22.   
  23.     public static void main(String[] args) {  
  24.         // 为了便于查阅,我们统一按照private、friendly、protected、public的顺序  
  25.         // 输出下列三种情况中变量的值  
  26.         // ParentClass类型,ParentClass对象  
  27.         ParentClass parentClass = new ParentClass();  
  28.         System.out.println("ParentClass parentClass = new ParentClass();");  
  29.         System.out.println(parentClass.getPrivateFieldValue());  
  30.         System.out.println(parentClass.friendlyField);  
  31.         System.out.println(parentClass.protectedField);  
  32.         System.out.println(parentClass.publicField);  
  33.         System.out.println();  
  34.         // ParentClass类型,SubClass对象  
  35.         ParentClass subClass = new SubClass();  
  36.         System.out.println("ParentClass subClass = new SubClass();");  
  37.         System.out.println(subClass.getPrivateFieldValue());  
  38.         System.out.println(subClass.friendlyField);  
  39.         System.out.println(subClass.protectedField);  
  40.         System.out.println(subClass.publicField);  
  41.         System.out.println();  
  42.         // SubClass类型,SubClass对象  
  43.         SubClass subClazz = new SubClass();  
  44.         System.out.println("SubClass subClazz = new SubClass();");  
  45.         System.out.println(subClazz.getPrivateFieldValue());  
  46.         System.out.println(subClazz.friendlyField);  
  47.         System.out.println(subClazz.protectedField);  
  48.         System.out.println(subClazz.publicField);  
  49.     }  
  50. }  

执行结果:
Java代码  收藏代码
  1. ParentClass parentClass = new ParentClass();  
  2. 父类变量--private  
  3. 父类变量--friendly  
  4. 父类变量--protected  
  5. 父类变量--public  
  6.   
  7. ParentClass subClass = new SubClass();  
  8. 子类变量--private  
  9. 父类变量--friendly  
  10. 父类变量--protected  
  11. 父类变量--public  
  12.   
  13. SubClass subClazz = new SubClass();  
  14. 子类变量--private  
  15. 子类变量--friendly  
  16. 子类变量--protected  
  17. 子类变量--public  

private的变量与其它三种访问权限变量的不同,这是由于方法的重写(override)而引起的。
分析上面的输出结果就会发现,变量的值取决于我们定义的变量的类型,而不是创建的对象
的类型。
当变量类型是父类(ParentClass)时,不管我们创建的对象是
父类(ParentClass)的还是子类(SubClass)的,都不存在属性覆盖的问题
Java代码  收藏代码
  1. package variableOverride;  
  2. class ParentClass {  
  3.     public static String staticField = "父类静态变量";  
  4.     public final String finalField = "父类常量";  
  5.     public static final String staticFinalField = "父类静态常量";  
  6.     }  
  7. public class SubClass extends ParentClass {  
  8. public static String staticField = "子类静态变量";  
  9. public final String finalField = "子类常量";  
  10. public static final String staticFinalField = "子类静态常量";  
  11. public static void main(String[] args) {  
  12. SubClass subClass = new SubClass();  
  13. System.out.println(SubClass.staticField);  
  14. // 注意,这里的subClass变量,不是SubClass类  
  15. System.out.println(subClass.finalField);  
  16. System.out.println(SubClass.staticFinalField);  
  17. }  
  18. }  

子类静态变量
子类常量
子类静态常量
虽然上面的结果中包含“子类静态变量”和“子类静态常量”,但这并不表示父类的“静态
变量”和“静态常量”可以被子类覆盖,因为它们都是属于类,而不属于对象。
总结:
1. 由于private变量受访问权限的限制,它不能被覆盖。
2. 属性的值取父类还是子类并不取决于我们创建对象的类型,而是取决于我们定义的变
量的类型。
3. friendly、protected和public修饰符并不影响属性的覆盖。
4. 静态变量和静态常量属于类,不属于对象,因此它们不能被覆盖。
5. 常量可以被覆盖。
6. 对于基本类型和对象,它们适用同样的覆盖规律。

4,final,finally,finalize
1. 在定义的时候初始化。
2. final变量可以在初始化块中初始化,不可以在静态初始化块中初始化。
3. 静态final变量可以在静态初始化块中初始化,不可以在初始化块中初始化。
4. final变量还可以在类的构造器中初始化,但是静态final变量不可以。
当final用来定义一个方法时,会有什么效果呢?正如大家所知,它表示这个方法不可以被
子类重写,但是它这不影响它被子类继承。
Java代码  收藏代码
  1. package variableOverride;  
  2.   
  3. class ParentClass {  
  4.     public final void TestFinal() {  
  5.     System.out.println("父类--这是一个final方法");  
  6.     }  
  7.     }  
  8.   
  9.   
  10. public class SubClass extends ParentClass {  
  11. /** 
  12. * 子类无法重写(override)父类的final方法,否则编译时会报错,但是子类可以继承父类的final方法 
  13. */  
  14. // public void TestFinal() {  
  15. // System.out.println("子类--重写final方法");  
  16. // }  
  17. public static void main(String[] args) {  
  18. SubClass sc = new SubClass();  
  19. sc.TestFinal();//父类--这是一个final方法  
  20. }  
  21. }  

具有private访问权限的方法也可以增加final修饰,但是由于子类
无法继承private方法,因此也无法重写它。编译器在处理private方法时,是按照final方法来对待的,这样可以提高该方法被调用时的效率。不过子类仍然可以定义同父类中的
private方法具有同样结构的方法,但是这并不会产生重写的效果,而且它们之间也不存在必
然联系。
final类不允许被继承,编译器在处理时把它的所有方法都当作
final的,因此final类比普通类拥有更高的效率。而由关键字abstract定义的抽象类含有必须由继承自它的子类重载实现的抽象方法, 因此无法同时用final和abstract来修饰同一个类。同样的道理,final也不能用来修饰接口。 final的类的所有方法都不能被重写,但这并不表示final的类的属性(变量)值也是不可改变的,要想做到final类的属性值不可改变,必须给它增 加final修饰.
Java代码  收藏代码
  1. public final class FinalTest {  
  2. int i = 10;  
  3. public static void main(String[] args) {  
  4. FinalTest ft = new FinalTest();  
  5. ft.i = 99;  
  6. System.out.println(ft.i); //99  
  7. }  
  8. }  

finally是处理异常时用的,不管是否发生异常,都会执行的语句,break,continue也不例外
Java代码  收藏代码
  1. package variableOverride;  
  2.   
  3. public final class FinallyTest {  
  4.     // 测试return语句  
  5.     public ReturnClass testReturn() {  
  6.         try {  
  7.             return new ReturnClass();  
  8.         } catch (Exception e) {  
  9.             e.printStackTrace();  
  10.         } finally {  
  11.             System.out.println("执行了finally语句");  
  12.         }  
  13.         return null;  
  14.     }  
  15.   
  16.     // 测试continue语句  
  17.     public void testContinue() {  
  18.         for (int i = 0; i < 3; i++) {  
  19.             try {  
  20.                 System.out.println(i);  
  21.                 if (i == 1) {  
  22.                     continue;  
  23.                 }  
  24.             } catch (Exception e) {  
  25.                 e.printStackTrace();  
  26.             } finally {  
  27.                 System.out.println("执行了finally语句");  
  28.             }  
  29.         }  
  30.     }  
  31.   
  32.     // 测试break语句  
  33.     public void testBreak() {  
  34.         for (int i = 0; i < 3; i++) {  
  35.             try {  
  36.                 System.out.println(i);  
  37.                 if (i == 1) {  
  38.                     break;  
  39.                 }  
  40.             } catch (Exception e) {  
  41.                 e.printStackTrace();  
  42.             } finally {  
  43.                 System.out.println("执行了finally语句");  
  44.             }  
  45.         }  
  46.     }  
  47.   
  48.     public static void main(String[] args) {  
  49.         FinallyTest ft = new FinallyTest();  
  50.         // 测试return语句  
  51.         ft.testReturn();  
  52.         System.out.println();  
  53.         // 测试continue语句  
  54.         ft.testContinue();  
  55.         System.out.println();  
  56.         // 测试break语句  
  57.         ft.testBreak();  
  58.     }  
  59. }  
  60.   
  61. class ReturnClass {  
  62.     public ReturnClass() {  
  63.         System.out.println("执行了return语句");  
  64.     }  
  65. }  

执行结果:
Java代码  收藏代码
  1. 执行了return语句  
  2. 执行了finally语句  
  3.   
  4. 0  
  5. 执行了finally语句  
  6. 1  
  7. 执行了finally语句  
  8. 2  
  9. 执行了finally语句  
  10.   
  11. 0  
  12. 执行了finally语句  
  13. 1  
  14. 执行了finally语句  



很明显,return、continue和break都没能阻止 finally语句块的执行。从输出的结果来看,return语句似乎在 finally语句块之前执行了,事实真的如此吗?我们来想想看,return语句的作用是什么呢?是退出当前的方法,并将值或对象返回。如果 finally语句块是在return语句之后执行的,那么return语句被执行后就已经退出当前方法了,finally语句块又如何能被执行呢?因 此,正确的执行顺序应该是这样的:编译器在编译return new ReturnClass();时,将它分成了两个步骤,new ReturnClass()和return,前一个创建对象的语句是在finally语句块之前被执行的,而后一个return语句是在finally语 句块之后执行的,也就是说finally语句块是在程序退出方法之前被执行的。同样,finally语句块是在循环被跳过(continue)和中断 (break)之前被执行的。

finalize()方法是Object类中定义的方法,是在GC清理它所从属的对象时被调用的,如果执行它的过程中抛出了无法捕
获的异常(uncaught exception),GC将终止对改对象的清理,并且该异常会被忽略;直到下一次GC开始清理这个对象时,它的finalize()会被再次调用。
Java代码  收藏代码
  1. package variableOverride;  
  2. public final class FinallyTest {  
  3. // 重写finalize()方法  
  4. protected void finalize() throws Throwable {  
  5. System.out.println("执行了finalize()方法");  
  6. }  
  7. public static void main(String[] args) {  
  8. FinallyTest ft = new FinallyTest();  
  9. ft = null;  
  10. System.gc(); //等价于Runtime.getRuntime().gc();  
  11. }  
  12. }  

执行结果:执行了finalize()方法
调用它们的作用只是建议垃圾收集器(GC)启动,清理无用的对象释放内存空间,但是GC
的启动并不是一定的,这由JAVA虚拟机来决定。直到 JAVA虚拟机停止运行,有些对象的
finalize()可能都没有被运行过,那么怎样保证所有对象的这个方法在JAVA虚拟机停止运行之前一定被调用呢?答案是我们可以调用System类的另一个方法:
Java代码  收藏代码
  1. public static void runFinalizersOnExit(boolean value) {  
  2. //other code  
  3. }  

传入true为参数,即可保证finalize方法一定执行,但该方法是不安全的,不建议使用。
5,java中参数传递
Java代码  收藏代码
  1. package variableOverride;  
  2.   
  3. public class ParamTest {  
  4.     // 初始值为0  
  5.     protected int num = 0;  
  6.   
  7.     // 为方法参数重新赋值  
  8.     public void change(int i) {  
  9.         i = 5;  
  10.     }  
  11.   
  12.     // 为方法参数重新赋值  
  13.     public void change(ParamTest t) {  
  14.         ParamTest tmp = new ParamTest();  
  15.         tmp.num = 9;  
  16.         t = tmp; //这里的t也是局部变量,和实参指向同一个对象,但现在该引用指向了新创建的tmp  
  17.     }  
  18.   
  19.     // 改变方法参数的值  
  20.     public void add(int i) {  
  21.         i += 10//这里的i为局部变量  
  22.     }  
  23.   
  24.     // 改变方法参数属性的值  
  25.     public void add(ParamTest pt) {  
  26.         pt.num += 20//pt和实参指向同一个对象,对pt指向对象值的改变就是对源对象值改变  
  27.     }  
  28.   
  29.     public static void main(String[] args) {  
  30.         ParamTest t = new ParamTest();  
  31.         System.out.println("参数--基本类型");  
  32.         System.out.println("原有的值:" + t.num);  
  33.         // 为基本类型参数重新赋值  
  34.         t.change(t.num);  
  35.         System.out.println("赋值之后:" + t.num);  
  36.         // 为引用型参数重新赋值  
  37.         t.change(t);  
  38.         System.out.println("运算之后:" + t.num);  
  39.         System.out.println();  
  40.         t = new ParamTest();  
  41.         System.out.println("参数--引用类型");  
  42.         System.out.println("原有的值:" + t.num);  
  43.         // 改变基本类型参数的值  
  44.         t.add(t.num);  
  45.         System.out.println("赋引用后:" + t.num);  
  46.         // 改变引用类型参数所指向对象的属性值  
  47.         t.add(t);  
  48.         System.out.println("改属性后:" + t.num);  
  49.     }  
  50. }  

执行结果:
参数--基本类型
原有的值:0
赋值之后:0
运算之后:0

参数--引用类型
原有的值:0
赋引用后:0
改属性后:20

String的长度实际上就是它的属性--char型数组value的长度。数组是没有length()方法的,
大家知道,在JAVA中,数组也被作为对象来处理,它的方法都继承自Object类。数组有一
个属性length,这也是它唯一的属性,对于所有类型的数组都是这样。

6,java中的字符
一个中文汉字可以保存在一个char变量里呢?因为在JAVA中,一
个char是2个字节(byte),而一个中文汉字是一个字符,也是2个字节。而英文字母都是
一个字节的,因此它也能保存到一个byte里,一个中文汉字却不能
字符串反串最简单的方法是使用java api本身自带的函数
Java代码  收藏代码
  1. public class StringReverse {  
  2. public static void main(String[] args) {  
  3. // 原始字符串  
  4. String s = "A quick brown fox jumps over the lazy dog.";  
  5. System.out.println("原始的字符串:" + s);  
  6. System.out.print("反转后字符串:");  
  7. StringBuffer buff = new StringBuffer(s);  
  8. // java.lang.StringBuffer类的reverse()方法可以将字符串反转  
  9. System.out.println(buff.reverse().toString());  
  10. }  

阅读(657) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~