Java程序由package+class组成,package对应目录的相对路径,class对应文件,如
E:\Workspaces\MyEclipse 10\JavaStudy\src\com\happyframework\javastudy\hello\Hello.java
- package com.happyframework.javastudy.hello;
-
- public final class Hello {
- public static void hello(){
- System.out.println("hello!");
- }
- }
关于class有如下几点规则:
App.java
- public class App {
- public static void main(String[] args) {
- com.happyframework.javastudy.hello.Hello.hello();
- }
- }
8种原子类型
除此之外的是interface、class和array。
小数类型的常量默认是double类型,声明float类型的常量需要使用F作为后缀。
- public class Program {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- float age = 28.0F;
- System.out.println(age);
- }
-
- }
String是拥有“值语义”的引用类型,字符串常量实现了“享元模式”,equals会按照内容进行比较,==按照地址比较。
- public class Program {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- String x = "段光伟";
- String y = new String("段光伟");
-
- System.out.println(x.equals(y)); // true
- System.out.println(x == y); // false
- }
-
- }
为了高效的修改字符串Java引入了StringBuffer。
- {
- StringBuffer sb =
- new StringBuffer()
- .append("段")
- .append("光")
- .append("伟");
-
- System.out.println(sb.toString());
- }
声明语法
DataType[]name 或 DataType name[]。
初始化语法
DataType[]name = new DataType[length]。
DataType[]name = new DataType[] { element1, element2, ...elementn}。
DataType[]name = { element1,element2, ...elementn}。
- public class Program {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- {
- String[] strs = { "段", "光", "伟" };
-
- for (String item : strs) {
- System.out.print(item);
- }
- }
- }
-
- }
多维数组
只有不等长多维数组DataType[][],没有DataType[xxx, xxx]。
- public class Program {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- task: {
- int age = 25;
-
- System.out.println("start");
-
- if (age < 30) {
- break task;
- }
-
- System.out.println("end");
- }
- }
- }
最近觉得label是个不错的东西,最起码多了一种选择。
Java中所有的赋值和方法调用都是“按值“处理的,引用类型的值是对象的地址,原始类型的值是其自身。
Java支持变长方法参数。
- public class Program {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- print("段光伟", "段光宇");
- print(new String[] { "段光伟", "段光宇" });
- }
-
- private static void print(String... args) {
- for (String item : args) {
- System.out.println(item);
- }
- }
- }
- public class Program {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- Point point = new Point(100);
-
- System.out.print(point);
- }
- }
-
- class Point {
- private int x = ;
- private int y = 0;
-
- public Point(int x, int y) {
- this.x = x;
- this.y = y;
- }
-
- public Point(int x) {
- this(x, x);
- }
-
- public String toString() {
- return "(x:" + this.x + ",y:" + this.y + ")";
- }
- }
注意:调用自身的构造方法是用this(xxx,xxx,...)来完成,且必须位于第一行。
Java中类似静态构造方法的结构,称之为:静态初始化代码块,与之对应的是实例初始化代码块,见下例:
- public class Program {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- System.out.println(Point.getValue());
- System.out.println(new Point());
- }
- }
-
- class Point {
- private static int value = 0;
-
- public static int getValue() {
- return value;
- }
-
- static {
- value++;
- }
-
- static {
- value++;
- }
-
- private int x = 0;
- private int y = 0;
-
- {
- this.x = 10;
- }
-
- {
- this.y = 10;
- }
-
- public String toString() {
- return "(x:" + this.x + ",y:" + this.y + ")";
- }
- }
继承使用 extends,抽象类和抽象方法使用abstract声明,向下转型使用 (ChildType)instance,判断是否是某个类型使用 instanceof,见下例:
- public class Program {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- printAnimal(new Animal());
- printAnimal(new Dog());
- }
-
- private static void printAnimal(Animal animal) {
- if(animal instanceof Dog){
- System.out.println("I am a " + (Dog) animal);
- }
- else
- {
- System.out.println("I am an " + animal);
- }
- }
- }
-
- class Animal {
- public String toString() {
- return "Animal";
- }
- }
-
- class Dog extends Animal {
- public String toString() {
- return "Dog";
- }
- }
Java中的重写规则比较灵活,具体如下:
- public class Program {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- Animal animal = new Animal();
- Animal dog = new Dog();
-
- animal.say();
- dog.say();
-
- animal.eat(animal);
- dog.eat(dog);
-
- System.out.println(animal.info());
- System.out.println(dog.info());
- }
- }
-
- class Animal {
- private String name = "Animal";
-
- protected void say() {
- System.out.println("Animal" + " " + this.name);
- }
-
- public void eat(Animal food) {
- System.out.println("Animal eat " + food);
- }
-
- public Object info() {
- return "Animal";
- }
-
- @Override
- public String toString() {
- return "Animal";
- }
- }
-
- class Dog extends Animal {
- private String name = "Dog";
-
- @Override
- public final void say() {
- System.out.println("Dog" + " " + this.name);
- }
-
- @Override
- public final void eat(Animal food) {
- super.eat(food);
-
- System.out.println("Dog eated");
- }
-
- @Override
- public final String info() {
- return "Dog";
- }
-
- @Override
- public final String toString() {
- return "Dog";
- }
- }
包的名字和项目路径下的目录路径相对应,比如:项目路径为:C:\Study,有一个Java源文件位于:C:\Study\com\happyframework\study\App.java,那么App.java的包名字必须为:com.happyframework.study,且 App.java 的第一行语句必须为:packagecom.happyframework.study。
Java支持三种导入语法:
- import static util.Helper.*;
-
- public class Program {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- puts("段光伟");
- }
- }
Java支持四种访问级别:public、private、protected 和 default(默认),类型和接口只能使用public 和 default,成员和嵌套类型可以使用所有,下面简单的解释一下 protected 和 default。
Java支持如下几种嵌套类:
代码示例
- public class Program {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- OuterClass outer = new OuterClass();
- OuterClass.InnerClass inner = outer.new InnerClass();
- OuterClass.InnerClass.InnerInnerClass innerInner = inner.new InnerInnerClass();
- outer.show();
- inner.show();
- innerInner.show();
-
- OuterClass.StaticNestedClass staticNested=new OuterClass.StaticNestedClass();
- OuterClass.StaticNestedClass.StaticNestedNestedClass staticNestedNested=new OuterClass.StaticNestedClass.StaticNestedNestedClass();
-
- staticNested.show();
- staticNestedNested.show();
- }
- }
-
- class OuterClass {
- int x = 1;
- static int i = 1;
-
- void show() {
- System.out.println(x);
- System.out.println(i);
- }
-
- class InnerClass {
- int y = 2;
-
- void show() {
- System.out.println(x);
- System.out.println(y);
- }
-
- class InnerInnerClass {
- int z = 3;
-
- void show() {
- System.out.println(OuterClass.this.x);
- System.out.println(y);
- System.out.println(z);
- }
- }
- }
-
- static class StaticNestedClass {
- static int j = 2;
-
- void show() {
- System.out.println(i);
- System.out.println(j);
- }
-
- static class StaticNestedNestedClass {
- static int k = 3;
-
- void show() {
- System.out.println(i);
- System.out.println(j);
- System.out.println(k);
- }
- }
- }
- }
特殊的inner class:local class
- public class LocalClassExample {
-
- static String staticValue = "static value";
- String instanceValue = "instance value";
-
- public void test() {
-
- final String finalLocalValue = "final local value";
-
- class LocalClass {
- void test() {
- System.out.println(staticValue);
- System.out.println(instanceValue);
- System.out.println(finalLocalValue);
- }
- }
-
- LocalClass local = new LocalClass();
- local.test();
- }
- }
除了inner class的规则之外,local class可以访问局部final变量,在Java8中有更多的改进。
特殊的local class:anonymous class
- public class Program {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- execute(new Action() {
- @Override
- public void execute() {
- System.out.println("执行业务逻辑");
- }
- });
- }
-
- static void execute(Action action) {
- System.out.println("事物开始");
- action.execute();
- System.out.println("事物结束");
- }
- }
-
- interface Action {
- void execute();
- }
不废话了,直接看代码:
- public final class Program {
- static final String STATIC_CONSTANTS = "STATIC_CONSTANTS";
- final String INSTANCE_CONSTANTS = "INSTANCE_CONSTANTS";
-
- public static void main(String[] args) {
- final String LOCAL_CONSTANTS = "LOCAL_CONSTANTS";
-
- System.out.println(STATIC_CONSTANTS);
- System.out.println(new Program().INSTANCE_CONSTANTS);
- System.out.println(LOCAL_CONSTANTS);
- new Program().test("PARAMETER_CONSTANTS");
- }
-
- public final void test(final String msg) {
- System.out.println(msg);
- }
- }
有一点需要注意的是:只有一种情况Java的常量是编译时常量(编译器会帮你替换),其它情况都是运行时常量,这种情况是:静态类型常量且常量的值可以编译时确定。
Java的接口可以包含方法签名、常量和嵌套类,见下例:
- public final class Program {
- public static void main(String[] args) {
- Playable.EMPTY.play();
-
- new Dog().play();
- }
- }
-
- interface Playable {
- Playable EMPTY = new EmptyPlayable();
-
- void play();
-
- class EmptyPlayable implements Playable {
-
- @Override
- public void play() {
- System.out.println("无所事事");
- }
-
- }
- }
-
- class Dog implements Playable {
-
- @Override
- public void play() {
- System.out.println("啃骨头");
- }
-
- }
Java枚举是class,继承自java.lang.Enum,枚举中可以定义任何类型可以定义的内容,构造方法只能是private或package private,枚举成员会被编译器动态翻译为枚举实例常量,见下例:
- public final class Program {
- public static void main(String[] args) {
- System.out.println(State.ON);
- System.out.println(State.OFF);
-
- for (State item : State.values()) {
- System.out.println(item);
- System.out.println(State.valueOf(item.name()));
- }
- }
- }
-
- enum State {
- ON(1), OFF(0);
-
- int value = 1;
-
- State(int value) {
- this.value = value;
- }
- }
调用枚举的构造方法格式是:常量名字(xxx, xxx),如果构造方法没有参数只需要:常量名子,如:
- enum State {
- ON, OFF
- }
Java中的异常分为checked和unchecked,checked异常必须声明在方法中或被捕获,这点我觉得比较好,必定:异常也是API的一部分,见下例:
- public final class Program {
- public static void main(String[] args) {
- try {
- test();
- } catch (Exception e) {
- System.out.println(e.getMessage());
- }
- }
-
- public static void test() throws Exception {
- throw new Exception("I am wrong!");
- }
- }
所有继承Exception的异常(除了RuntimeException和它的后代之外)都是checked异常。
Java提供了原始类型对应的引用类型,在1.5之后的版本还提供了自动装箱和自动拆箱,结合最新版本的泛型,几乎可以忽略这块。
- import java.util.*;
-
- public final class Program {
- public static void main(String[] args) {
- ArrayList list = new ArrayList();
-
- list.add(1);
- int item1 = (Integer) list.get(0);
-
- System.out.println(item1);
- }
- }
注意:自动装箱和自动拆箱是Java提供的语法糖。
Java的泛型是编译器提供的语法糖,官方称之为:类型参数搽除,先看一下语法,然后总结一点规律:
测试代码
- static <T> void puts(T msg) {
- println(msg);
- }
-
- static void println(Object msg) {
- System.out.println("Object:" + msg);
- }
-
- static void println(String msg) {
- System.out.println("String:" + msg);
- }
调用泛型方法
- System.out.println("generic method test");
- puts("hello");
- Program.<String> puts("hello");
输出的结果是
- generic method test
- Object:hello
- Object:hello
测试代码
- class TestGenericClass<T> {
- T value;
-
- void setValue(T value) {
- this.value = value;
- }
- }
调用代码
- System.out.println("generic class test");
- System.out.println(t.value);
输出结果
- generic class test
- 1
测试代码
- interface TestInterface<T> {
- void test(T item);
- }
-
- class TestInterfaceImp1 implements TestInterface<String> {
-
- @Override
- public void test(String item) {
- System.out.println(item);
- }
- }
-
- class TestInterfaceImp2<T> implements TestInterface<T> {
-
- @Override
- public void test(T item) {
- System.out.println(item);
- }
- }
调用代码
- System.out.println("generic interface test");
- TestInterface<String> testInterface1 = new TestInterfaceImp1();
- testInterface1.test("hi");
- for (Method item : testInterface1.getClass().getMethods()) {
- if (item.getName() == "test") {
- System.out.println(item.getParameterTypes()[0].getName());
- }
- }
-
- TestInterface<String> testInterface2 = new TestInterfaceImp2<>();
- testInterface2.test("hi");
- for (Method item : testInterface2.getClass().getMethods()) {
- if (item.getName() == "test") {
- System.out.println(item.getParameterTypes()[0].getName());
- }
- }
输出结果
- generic interface test
- hi
- java.lang.String
- java.lang.Object
- hi
- java.lang.Object
测试代码
- class Animal {
- }
-
- class Dog extends Animal {
- }
-
- class Base<T extends Animal> {
- public void test(T item) {
- System.out.println("Base:" + item);
- }
- }
-
- class Child extends Base<Dog> {
-
- @Override
- public void test(Dog item) {
- System.out.println("Child:" + item);
- }
- }
调用代码
- System.out.println("bounded type parameters test");
- Base<Dog> base = new Child();
- base.test(new Dog());
- for (Method item : base.getClass().getMethods()) {
- if (item.getName() == "test") {
- System.out.println(item.getParameterTypes()[0].getName());
- }
- }
输出结果
- bounded type parameters test
- Child:Dog@533c2ac3
- Dog
- Animal
- class Base {
- public void test(T item) {
- System.out.println("Base:" + item);
- }
- }
- class Base {
- public void test(Animal item) {
- System.out.println("Base:" + item);
- }
- }
- class Child extends Base {
- @Override
- public void test(Animal item) {
- this.test((Dog)item);
- }
-
- public void test(Dog item) {
- System.out.println("Child:" + item);
- }
- }
- System.out.println("bounded type parameters test");
- Base base = new Child();
- base.test(new Dog());
- for (Method item : base.getClass().getMethods()) {
- if (item.getName() == "test") {
- System.out.println(item.getParameterTypes()[0].getName());
- }
- }
这里说的不一定正确,特别是Java泛型的约束支持&(如:可以约束实行多个接口),不过过程估计差别不大,我没有看Java语言规范,这里只是大概的猜测。
这几天完成了Java基本语法的学习,关于一些高级特性在后面再慢慢总结,如:运行时进程模型、类型加载机制、反射、注解、动态代理等。