Java学习注意事项
一个Java文件中可以包含多个类。
如果有public类,则文件名必须和public类一样。
例如:
1 class Pie { 2 void f(){ 3 System.out.println("Pie.f()"); 4 } 5 } 6 7 class Cake { 8 public static void main(String[] args){ 9 Pie x = new Pie(); 10 x.f(); 11 } 12 } 13 14 class Cake1 { 15 public static void main(String[] args){ 16 Pie x = new Pie(); 17 x.f(); 18 } 19 }
该文件名可以是Cake2.java或者其它。但如果该文件中有public 类,则文件名必须和public 类名一样。
上述文件编译产生如下的文件:
编译和运行命令如下:
1 关于类的访问权限控制:public 或者什么都不写(包访问权限,其它包的类不能访问该类)。
2 方法和字段的访问权限顺序从大到小:Public, protected, 默认(包访问权限), private。
2.1 protected 修饰的成员,如果其它package中的类继承了该类,就可以访问该成员。比默认的权限高。
3 使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。
4 由于final变量和static变量可以说都只能存一个数据,他们惟一的区别是static变量是属于类的,是类变量,只会被加载一次。
5 final和abstract 修饰的类,第一个不能继承,第二个继承必须实现存在的abstract方法。
6 abstract方法所在的类必须用abstract修饰。abstract修饰的类不能实例化,可以不存在抽象方法。
关于final
使用final的原因有两个。效率/设计。早期的编译器会针对final方法,进行特殊的优化。但是现在的编译器不推荐用户使用final关键字,
编译器和JVM会去处理相关的效率问题。
特别的,final方法不能被覆盖。因为private方法是不能够继承的,所以private 方法隐式的是final的。
"覆盖"只有在某方法是基类的接口的一部分时才会出现。如果某方法为private,它就不是基类的接口的一部分。
由于private方法无法触及而且能有效的隐藏,所以除了把它看成是因为它所属的类的组织结构的原因而存在外,其他任何事物都不需要考虑到它。
继承的初始化顺序
1 package reusing; 2 class Insect{ 3 private int i = 9; 4 protected int j; 5 public Insect() { 6 System.out.println("i = " + i + ", j = " + j); 7 j = 39; 8 } 9 private static int x1 = printInit("static Insect x1.initalized"); 10 static int printInit(String s){ 11 System.out.println(s); 12 return 47; 13 } 14 } 15 public class Beetle extends Insect{ 16 private int k = printInit("Beetle.k initalized"); 17 public Beetle(){ 18 System.out.println("k = " + k); 19 System.out.println("j = " + j); 20 } 21 private static int x2 = printInit("static Beetle x2.initalized"); 22 public static void main(String[] args){ 23 System.out.println("Bettle Constructor"); 24 Beetle b = new Beetle(); 25 } 26 27 /* 28 * static Insect x1.initalized 29 * static Beetle x2.initalized 30 * Bettle Constructor 31 * i = 9, j = 0 32 * Beetle.k initalized 33 * k = 47 34 * j = 39 35 * 36 */ 37 }
构造器中方法调用初始化特点及原则
1 package ploymorphism; 2 3 class Glyph { 4 void draw() { 5 System.out.println("Glyph.draw()"); 6 } 7 8 Glyph() {//1-0-0 9 System.out.println("Glyph() before draw()");//2 10 draw();//3 11 System.out.println("Glyph() after draw()");//5 12 } 13 } 14 15 class RoundGlyph extends Glyph { 16 private int radius = 1;//6 17 18 RoundGlyph(int r) {//1-0 19 radius = r;//7 20 System.out.println("RoundGlyph.RoundGlyph(), radius = " + radius);//8 21 } 22 23 void draw() {//3-0 24 System.out.println("RoundGlyph.draw(), radius = " + radius);//4 25 } 26 } 27 28 public class PolyConstructors { 29 public static void main(String[] args) { 30 new RoundGlyph(5); //1 31 } 32 } 33 34 /* 35 * 1) 在其它任何事物发生前,将分配给对象的存储空间初始化成二进制的零 36 * 2) 调用基类构造器。如上例,调用被覆盖后的draw()方法(要在调用RoundGlyph构造器之前调用), 37 * 由于步骤1的缘故,我们此时发现radius的值为0 38 * 3) 按照声明的顺序调用成员的初始化方法 39 * 4) 调用导出类的构造器的主题。 40 * 41 */ 42 /* 43 * 编写构造器的准则 44 * 45 * 用尽可能简单的方法使对象进入状态; 46 * 如果可以的话,尽量避免调用其它方法; 47 * 在构造器内唯一安全能够调用的方法是基类中的final(private也自动是final)方法; 48 * 应该朝着上述的方向努力。 49 * 50 */ 51
Java中的堆栈实现,用到内部类
1 class LinkedStack<T> { 2 /* 3 * 内部类模拟堆栈,Node<U>也是泛型,它拥有自己的类型参数 4 */ 5 private static class Node<U> { 6 U item; 7 Node<U> next; 8 9 Node() { 10 item = null; 11 next = null; 12 } 13 14 Node(U item, Node<U> next) { 15 this.item = item; 16 this.next = next; 17 } 18 19 boolean end() { 20 return item == null && next == null; 21 } 22 } 23 24 private Node<T> top = new Node<T>(); 25 26 public void push(T item) { 27 top = new Node<T>(item, top); 28 } 29 30 public T pop() { 31 T result = top.item; 32 if (!top.end()) { 33 top = top.next; 34 } 35 return result; 36 } 37 38 public static void main(String[] args) { 39 LinkedStack<String> lss = new LinkedStack<String>(); 40 for (String s : "Phaser on stun!".split(" ")) { 41 lss.push(s); 42 } 43 String s; 44 while ((s = lss.pop()) != null) { 45 System.out.println(s); 46 } 47 } 48 }
Java能不能实例化访问私有方法?
1 该问题要分情况的,如果在类定义中实例化该对象,则可以通过引用访问该对象的所有内容。
2 如果是在类的定义外实例化,则只可以访问非私有的属性。
java父类的构造器私有了, 怎么继承?
private只能本类中使用,其他的都用不了,所以也不能继承。
不过可以通过曲线救国
在父类里提供一个方法,该方法返回父类的对象,然后子类这时可以通过继承方法获取父类的对象。
一般构造器私有比较常用的就是单态了(工具类有的也这样用或者其他)
Java考题练习,继承、访问权限、多态、初始化
1 class Test { 2 private int day; 3 4 private Test(int d) { 5 day = d; 6 } 7 8 private void print() { 9 System.out.println("I am in Test"); 10 } 11 } 12 13 class DemoTest extends Test { 14 private DemoTest() { 15 super(2); 16 } 17 18 public void print() { 19 System.out.println("I am in DemoTest"); 20 } 21 22 public static void main(String[] args) { 23 DemoTest test = new DemoTest(); 24 test.print(); 25 } 26 } 27 28 /* 29 编译不通过,父类构造器私有,不能继承。把Test的private去掉即可 30 多态在这里没有发生,子类不能够覆盖父类的私有方法 31 */
文件Parcel2还有内部类,编译后是如下的三个class文件
StringBuffer的作用以及赋值修改
观察下面的代码
1 package sunjava; 2 3 public class Foo { 4 static void operate(StringBuffer a, StringBuffer b){ 5 a.append(b); 6 b = a; 7 } 8 public static void main(String[] args){ 9 StringBuffer a = new StringBuffer("A"); 10 StringBuffer b = new StringBuffer("B"); 11 operate(a, b); 12 System.out.println(a + "," + b); 13 } 14 /* 15 * append 函数的作用改变a的值,但是b = a 不能够改变b的值 16 * 17 * outPut: 18 * AB,B 19 * 20 */ 21 }
和下面的代码对比,会得出更加直观的效果。
1 package sunjava; 2 3 public class No6 { 4 public static void stringReplace(String textString){ 5 textString = textString.replace("j", "i"); //testString 新赋值了一个,与原来的无关 6 } 7 public static void bufferReplace(StringBuffer textBuffer){ 8 textBuffer.append("C"); //textBuffer在原来的上面加了一个C,源字符串被修改 9 } 10 11 public static void main(String[] args){ 12 String textString = new String("java"); 13 StringBuffer textBuffer = new StringBuffer("java"); 14 stringReplace(textString); 15 bufferReplace(textBuffer); 16 17 System.out.println(textString + textBuffer); 18 } 19 /* 20 * 注意StringBuffer类和String之间的区别 21 * 22 * outputs: 23 * 24 * javajavaC 25 */ 26 }
- 注意Overrride和Overload之间的不同点
- Java 内部类 分四种:成员内部类、局部内部类、静态内部类和匿名内部类。
- java成员变量的初始化顺序