Java:Java快速入門

你好,世界!

源代碼組織方式

Java程序由package+class組成,package對應目錄的相對路徑,class對應文件,如java

E:\Workspaces\MyEclipse 10\JavaStudy\src\com\happyframework\javastudy\hello\Hello.java數組

1 package com.happyframework.javastudy.hello;
2 
3 public final class Hello {
4     public static void hello(){
5         System.out.println("hello!");
6     }
7 }

關於class有以下幾點規則:app

  1. 文件的名字必須和class的名字一致(public級別的class名字)。
  2. 文件必須只包含一個public訪問基本的class(能夠包含多個非public級別的class)。
  3. package名字必須和目錄一致。

入口方法

App.javaide

1 public class App {
2     public static void main(String[] args) {
3         com.happyframework.javastudy.hello.Hello.hello();
4     }
5 }

最終的項目結構

數據類型

8種原子類型學習

  1. 整數類型:byte、short、int和long。
  2. 小數類型:float和double。
  3. 字符類型:char。
  4. 布爾類型:bool。

除此以外的是interface、class和array。測試

小數類型的常量默認是double類型,聲明float類型的常量須要使用F做爲後綴。this

 1 public class Program {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7             float age = 28.0F;
 8             System.out.println(age);
 9     }
10 
11 }

運算符

  1. 算術運算符:+、-、*、/ 和 %,兩個整數相除,結果仍是整數。
  2. 賦值運算符:=、+=、-=、*=、/=、%=、&=、|=、~=、^=、<<=、>>= 、 >>>=、++ 和 --。
  3. 比較運算符:==、!=、<、<=、> 和 >=。
  4. 邏輯運算符:&&、|| 和 !。
  5. 位運算符:&、|、~、^、<<、>> 和 >>>。

字符串

String是擁有「值語義」的引用類型,字符串常量實現了「享元模式」,equals會按照內容進行比較,==按照地址比較。spa

 1 public class Program {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7         String x = "段光偉";
 8         String y = new String("段光偉");
 9         
10         System.out.println(x.equals(y)); // true
11         System.out.println(x == y); // false
12     }
13 
14 }

爲了高效的修改字符串Java引入了StringBuffer。翻譯

1         {
2             StringBuffer sb = 
3                     new StringBuffer()
4                     .append("段")
5                     .append("光")
6                     .append("偉");
7             
8             System.out.println(sb.toString());
9         }

數組

聲明語法代理

DataType[] name 或 DataType name[]。

初始化語法

DataType[] name = new DataType[length]。

DataType[] name = new DataType[] { element1, element2, ...elementn }。

DataType[] name = { element1, element2, ...elementn }。

 1 public class Program {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7         {
 8             String[] strs = { "段", "光", "偉" };
 9 
10             for (String item : strs) {
11                 System.out.print(item);
12             }
13         }
14     }
15 
16 }

多維數組

只有不等長多維數組DataType[][],沒有DataType[xxx, xxx]。

控制結構

  1. 條件:if-else if-else、switch-case-default和三元運算符(?:)。
  2. 循環:while、do-while、for和foreach。
  3. Labeled block。
 1 public class Program {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7         task: {
 8             int age = 25;
 9 
10             System.out.println("start");
11 
12             if (age < 30) {
13                 break task;
14             }
15 
16             System.out.println("end");
17         }
18     }
19 }

最近以爲label是個不錯的東西,最起碼多了一種選擇。

方法

Java中全部的賦值和方法調用都是「按值「處理的,引用類型的值是對象的地址,原始類型的值是其自身。

Java支持變長方法參數。

 1 public class Program {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7         print("段光偉", "段光宇");
 8         print(new String[] { "段光偉", "段光宇" });
 9     }
10 
11     private static void print(String... args) {
12         for (String item : args) {
13             System.out.println(item);
14         }
15     }
16 }

 1 public class Program {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7         Point point = new Point(100);
 8 
 9         System.out.print(point);
10     }
11 }
12 
13 class Point {
14     private int x = 0;
15     private int y = 0;
16 
17     public Point(int x, int y) {
18         this.x = x;
19         this.y = y;
20     }
21 
22     public Point(int x) {
23         this(x, x);
24     }
25 
26     public String toString() {
27         return "(x:" + this.x + ",y:" + this.y + ")";
28     }
29 }

注意:調用自身的構造方法是用this(xxx,xxx,...)來完成,且必須位於第一行。

靜態成員

Java中相似靜態構造方法的結構,稱之爲:靜態初始化代碼塊,與之對應的是實例初始化代碼塊,見下例:

 1 public class Program {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7         System.out.println(Point.getValue());
 8         System.out.println(new Point());
 9     }
10 }
11 
12 class Point {
13     private static int value = 0;
14 
15     public static int getValue() {
16         return value;
17     }
18 
19     static {
20         value++;
21     }
22 
23     static {
24         value++;
25     }
26 
27     private int x = 0;
28     private int y = 0;
29 
30     {
31         this.x = 10;
32     }
33 
34     {
35         this.y = 10;
36     }
37 
38     public String toString() {
39         return "(x:" + this.x + ",y:" + this.y + ")";
40     }
41 }

繼承

繼承使用 extends,抽象類和抽象方法使用abstract聲明,向下轉型使用 (ChildType)instance,判斷是不是某個類型使用 instanceof,見下例:

 1 public class Program {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7         printAnimal(new Animal());
 8         printAnimal(new Dog());
 9     }
10 
11     private static void printAnimal(Animal animal) {
12         if(animal instanceof Dog){
13             System.out.println("I am a " + (Dog) animal);
14         }
15         else
16         {
17             System.out.println("I am an " + animal);
18         }
19     }
20 }
21 
22 class Animal {
23     public String toString() {
24         return "Animal";
25     }
26 }
27 
28 class Dog extends Animal {
29     public String toString() {
30         return "Dog";
31     }
32 }

重寫

Java中的重寫規則比較靈活,具體以下:

  1. 除了 private 修飾以外的全部實例方法均可以重寫,不須要顯式的聲明。
  2. 重寫的方法爲了顯式的表達重寫這一律念,使用 @Override進行註解。
  3. 重寫的方法能夠修改訪問修飾符和返回類型,只要和父類的方法兼容(訪問級別更高,返回類型更具體)。
  4. 能夠使用final將某個方法標記爲不可重寫。
  5. 在構造方法中使用 super(xxx, xxx)調用父類構造方法,在常規實例方法中使用 super.method(xxx, xxx)調用父類方法。
  6. Java不支持覆蓋(new)。
 1 public class Program {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7         Animal animal = new Animal();
 8         Animal dog = new Dog();
 9 
10         animal.say();
11         dog.say();
12 
13         animal.eat(animal);
14         dog.eat(dog);
15         
16         System.out.println(animal.info());
17         System.out.println(dog.info());
18     }
19 }
20 
21 class Animal {
22     private String name = "Animal";
23 
24     protected void say() {
25         System.out.println("Animal" + " " + this.name);
26     }
27 
28     public void eat(Animal food) {
29         System.out.println("Animal eat " + food);
30     }
31 
32     public Object info() {
33         return "Animal";
34     }
35     
36     @Override
37     public String toString() {
38         return "Animal";
39     }
40 }
41 
42 class Dog extends Animal {
43     private String name = "Dog";
44 
45     @Override
46     public final void say() {
47         System.out.println("Dog" + " " + this.name);
48     }
49 
50     @Override
51     public final void eat(Animal food) {
52         super.eat(food);
53         
54         System.out.println("Dog eated");
55     }
56 
57     @Override
58     public final String info() {
59         return "Dog";
60     }
61 
62     @Override
63     public final String toString() {
64         return "Dog";
65     }
66 }

包的名字和項目路徑下的目錄路徑相對應,好比:項目路徑爲:C:\Study,有一個Java源文件位於:C:\Study\com\happyframework\study\App.java,那麼App.java的包名字必須爲:com.happyframework.study,且 App.java 的第一行語句必須爲:package com.happyframework.study。

Java支持三種導入語法:

  1. 導入類型:import xxx.xxx.xxxClass。
  2. 導入包:import xxx.xxx.xxx.*。
  3. 導入靜態成員:import static xxx.xxx.*。
 1 import static util.Helper.*;
 2 
 3 public class Program {
 4 
 5     /**
 6      * @param args
 7      */
 8     public static void main(String[] args) {
 9         puts("段光偉");
10     }
11 }

訪問級別

Java支持四種訪問級別:public、private、protected 和 default(默認),類型和接口只能使用public 和 default,成員和嵌套類型能夠使用全部,下面簡單的解釋一下 protected 和 default。

  • protected 修飾過的成員只能被本身、子類和同一個包裏的(不包括子包)其餘類型訪問。
  • default 修改過的類型或成員只能被本身和同一個包裏的(不包括子包)其餘類型訪問。

嵌套類

Java支持以下幾種嵌套類:

  1. nested class,定義在類型內部的類型。
    1. static nested class,使用 static 聲明的 nested class,static nested class 能夠訪問全部外部類的靜態成員。
    2. inner class,沒有使用 static 聲明的 nested class,inner class 能夠訪問全部外部類的實例成員,inner class 不能定義靜態成員。

代碼示例

 1 public class Program {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7         OuterClass outer = new OuterClass();
 8         OuterClass.InnerClass inner = outer.new InnerClass();
 9         OuterClass.InnerClass.InnerInnerClass innerInner = inner.new InnerInnerClass();
10         outer.show();
11         inner.show();
12         innerInner.show();
13         
14         OuterClass.StaticNestedClass staticNested=new OuterClass.StaticNestedClass();
15         OuterClass.StaticNestedClass.StaticNestedNestedClass staticNestedNested=new OuterClass.StaticNestedClass.StaticNestedNestedClass();
16         
17         staticNested.show();
18         staticNestedNested.show();
19     }
20 }
21 
22 class OuterClass {
23     int x = 1;
24     static int i = 1;
25 
26     void show() {
27         System.out.println(x);
28         System.out.println(i);
29     }
30 
31     class InnerClass {
32         int y = 2;
33 
34         void show() {
35             System.out.println(x);
36             System.out.println(y);
37         }
38 
39         class InnerInnerClass {
40             int z = 3;
41 
42             void show() {
43                 System.out.println(OuterClass.this.x);
44                 System.out.println(y);
45                 System.out.println(z);
46             }
47         }
48     }
49 
50     static class StaticNestedClass {
51         static int j = 2;
52 
53         void show() {
54             System.out.println(i);
55             System.out.println(j);
56         }
57 
58         static class StaticNestedNestedClass {
59             static int k = 3;
60 
61             void show() {
62                 System.out.println(i);
63                 System.out.println(j);
64                 System.out.println(k);
65             }
66         }
67     }
68 }

特殊的inner class:local class

 1 public class LocalClassExample {
 2 
 3     static String staticValue = "static value";
 4     String instanceValue = "instance value";
 5 
 6     public void test() {
 7 
 8         final String finalLocalValue = "final local value";
 9 
10         class LocalClass {
11             void test() {
12                 System.out.println(staticValue);
13                 System.out.println(instanceValue);
14                 System.out.println(finalLocalValue);
15             }
16         }
17 
18         LocalClass local = new LocalClass();
19         local.test();
20     }
21 }

除了inner class的規則以外,local class能夠訪問局部final變量,在Java8中有更多的改進。

特殊的local class:anonymous class

 1 public class Program {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7         execute(new Action() {
 8             @Override
 9             public void execute() {
10                 System.out.println("執行業務邏輯");
11             }
12         });
13     }
14 
15     static void execute(Action action) {
16         System.out.println("事物開始");
17         action.execute();
18         System.out.println("事物結束");
19     }
20 }
21 
22 interface Action {
23     void execute();
24 }

常量

不廢話了,直接看代碼:

 1 public final class Program {
 2     static final String STATIC_CONSTANTS = "STATIC_CONSTANTS";
 3     final String INSTANCE_CONSTANTS = "INSTANCE_CONSTANTS";
 4 
 5     public static void main(String[] args) {
 6         final String LOCAL_CONSTANTS = "LOCAL_CONSTANTS";
 7 
 8         System.out.println(STATIC_CONSTANTS);
 9         System.out.println(new Program().INSTANCE_CONSTANTS);
10         System.out.println(LOCAL_CONSTANTS);
11         new Program().test("PARAMETER_CONSTANTS");
12     }
13 
14     public final void test(final String msg) {
15         System.out.println(msg);
16     }
17 }

有一點須要注意的是:只有一種狀況Java的常量是編譯時常量(編譯器會幫你替換),其它狀況都是運行時常量,這種狀況是:靜態類型常量且常量的值能夠編譯時肯定。

接口

Java的接口能夠包含方法簽名、常量和嵌套類,見下例:

 1 public final class Program {
 2     public static void main(String[] args) {
 3         Playable.EMPTY.play();
 4 
 5         new Dog().play();
 6     }
 7 }
 8 
 9 interface Playable {
10     Playable EMPTY = new EmptyPlayable();
11 
12     void play();
13 
14     class EmptyPlayable implements Playable {
15 
16         @Override
17         public void play() {
18             System.out.println("無所事事");
19         }
20 
21     }
22 }
23 
24 class Dog implements Playable {
25 
26     @Override
27     public void play() {
28         System.out.println("啃骨頭");
29     }
30 
31 }

枚舉

Java枚舉是class,繼承自java.lang.Enum,枚舉中能夠定義任何類型能夠定義的內容,構造方法只能是private或package private,枚舉成員會被編譯器動態翻譯爲枚舉實例常量,見下例:

 1 public final class Program {
 2     public static void main(String[] args) {
 3         System.out.println(State.ON);
 4         System.out.println(State.OFF);
 5 
 6         for (State item : State.values()) {
 7             System.out.println(item);
 8             System.out.println(State.valueOf(item.name()));
 9         }
10     }
11 }
12 
13 enum State {
14     ON(1), OFF(0);
15 
16     int value = 1;
17 
18     State(int value) {
19         this.value = value;
20     }
21 }

調用枚舉的構造方法格式是:常量名字(xxx, xxx),若是構造方法沒有參數只須要:常量名子,如:

1 enum State {
2     ON, OFF
3 }

異常

Java中的異常分爲checked和unchecked,checked異常必須聲明在方法中或被捕獲,這點我以爲比較好,一定:異常也是API的一部分,見下例:

 1 public final class Program {
 2     public static void main(String[] args) {
 3         try {
 4             test();
 5         } catch (Exception e) {
 6             System.out.println(e.getMessage());
 7         }
 8     }
 9 
10     public static void test() throws Exception {
11         throw new Exception("I am wrong!");
12     }
13 }

全部繼承Exception的異常(除了RuntimeException和它的後代以外)都是checked異常。

裝箱和拆箱

Java提供了原始類型對應的引用類型,在1.5以後的版本還提供了自動裝箱和自動拆箱,結合最新版本的泛型,幾乎能夠忽略這塊。

 1 import java.util.*;
 2 
 3 public final class Program {
 4     public static void main(String[] args) {
 5         ArrayList list = new ArrayList();
 6         
 7         list.add(1);
 8         int item1 = (Integer) list.get(0);
 9         
10         System.out.println(item1);
11     }
12 }

注意:自動裝箱和自動拆箱是Java提供的語法糖。

泛型

Java的泛型是編譯器提供的語法糖,官方稱之爲:類型參數搽除,先看一下語法,而後總結一點規律:

泛型方法

測試代碼

 1     static <T> void puts(T msg) {
 2         println(msg);
 3     }
 4 
 5     static void println(Object msg) {
 6         System.out.println("Object:" + msg);
 7     }
 8 
 9     static void println(String msg) {
10         System.out.println("String:" + msg);
11     }

調用泛型方法

1         System.out.println("generic method test");
2         puts("hello");
3         Program.<String> puts("hello");

輸出的結果是

1 generic method test
2 Object:hello
3 Object:hello

泛型類

測試代碼

1 class TestGenericClass<T> {
2     T value;
3 
4     void setValue(T value) {
5         this.value = value;
6     }
7 }

調用代碼

1         System.out.println("generic class test");
2         System.out.println(t.value);

輸出結果

1 generic class test
2 1

泛型接口

測試代碼

 1 interface TestInterface<T> {
 2     void test(T item);
 3 }
 4 
 5 class TestInterfaceImp1 implements TestInterface<String> {
 6 
 7     @Override
 8     public void test(String item) {
 9         System.out.println(item);
10     }
11 }
12 
13 class TestInterfaceImp2<T> implements TestInterface<T> {
14 
15     @Override
16     public void test(T item) {
17         System.out.println(item);
18     }
19 }

調用代碼

 1         System.out.println("generic interface test");
 2         TestInterface<String> testInterface1 = new TestInterfaceImp1();
 3         testInterface1.test("hi");
 4         for (Method item : testInterface1.getClass().getMethods()) {
 5             if (item.getName() == "test") {
 6                 System.out.println(item.getParameterTypes()[0].getName());
 7             }
 8         }
 9 
10         TestInterface<String> testInterface2 = new TestInterfaceImp2<>();
11         testInterface2.test("hi");
12         for (Method item : testInterface2.getClass().getMethods()) {
13             if (item.getName() == "test") {
14                 System.out.println(item.getParameterTypes()[0].getName());
15             }
16         }

輸出結果

1 generic interface test
2 hi
3 java.lang.String
4 java.lang.Object
5 hi
6 java.lang.Object

類型參數約束

測試代碼

 1 class Animal {
 2 }
 3 
 4 class Dog extends Animal {
 5 }
 6 
 7 class Base<T extends Animal> {
 8     public void test(T item) {
 9         System.out.println("Base:" + item);
10     }
11 }
12 
13 class Child extends Base<Dog> {
14 
15     @Override
16     public void test(Dog item) {
17         System.out.println("Child:" + item);
18     }
19 }

調用代碼

1         System.out.println("bounded type parameters test");
2         Base<Dog> base = new Child();
3         base.test(new Dog());
4         for (Method item : base.getClass().getMethods()) {
5             if (item.getName() == "test") {
6                 System.out.println(item.getParameterTypes()[0].getName());
7             }
8         }

輸出結果

1 bounded type parameters test
2 Child:Dog@533c2ac3
3 Dog
4 Animal

類型搽除過程

  1. 將泛型定義中的類型參數去掉。
    class Base {
        public void test(T item) {
            System.out.println("Base:" + item);
        }
    }
  2. 將T換成extends指定的約束類型,默認是Object。
    1 class Base {
    2     public void test(Animal item) {
    3         System.out.println("Base:" + item);
    4     }
    5 }
  3. 若是有非泛型類型繼承或實現了泛型基類或接口,並且進行了重寫,根據狀況,編譯器會自動生成一些方法。
     1 class Child extends Base {
     2     @Override
     3     public void test(Animal item) {
     4         this.test((Dog)item);
     5     }
     6     
     7     public void test(Dog item) {
     8         System.out.println("Child:" + item);
     9     }
    10 }
  4. 根據泛型參數的實際參數搽除調用代碼。
    1         System.out.println("bounded type parameters test");
    2         Base base = new Child();
    3         base.test(new Dog());
    4         for (Method item : base.getClass().getMethods()) {
    5             if (item.getName() == "test") {
    6                 System.out.println(item.getParameterTypes()[0].getName());
    7             }
    8         }

 這裏說的不必定正確,特別是Java泛型的約束支持&(如:能夠約束實行多個接口),不過過程估計差異不大,我沒有看Java語言規範,這裏只是大概的猜想。

備註

這幾天完成了Java基本語法的學習,關於一些高級特性在後面再慢慢總結,如:運行時進程模型、類型加載機制、反射、註解、動態代理等。

相關文章
相關標籤/搜索