2014-12-03

Java 入门

基本语法

hello world

变量

引号

单引号引的数据 是char类型的 双引号引的数据 是String类型的 单引号只能引一个字符 而双引号可以引0个及其以上 在这里的单引号完全可以换成双引号 append方法是重写方法,里面既可以放char类型的又可以放String类型的数据,还有其他类型的等等 建议看一下StringBuffer的api方法

基本数据结构

循环

if-else

switch

函数

  • 函数定义
  • 函数调用
  • 函数传参
  • 返回值

类和对象

类就是定义一个模板

类的一般形式

// 定义一个类
public class Human{
	String name;
	String sex;
	String addr;
	int age;
	
	void work(){
		System.out.println("我在工作");
	}
	void eat(){
		System.out.println("我在吃饭");
	}	
}

修饰符说明:

  • private 只有本类可见
  • protect 本类 子类以及同一个包中的类可见
  • 默认(无修饰符) 对本类 子类(同一个包内的, 包外的子类是不行的)以及同一个包中的类可见,即 protected
  • public 对任何类可见

方法的重载

在 java 中支持两个或多个同名的方法. 但他们的参数个数和类型必须有差别. 这种情况就是方法的重载(overloading). 重载是 java 实现多态的方式之一. 当调用这些同名的方法是, java 根据参数的类型以及参数的数目来确定到底调用哪个方法. 注意: 返回值类型并不能起到区分方法的作用.

对象

对象的创建和使用

构造函数

通过创建对象的介绍, 引入构造函数 构造函数的名字必须和类名相同并且没有返回值 构造函数是可以重载的. 而且重载的这些构造函数是可以相互调用的.

static 关键字

使用 static 修饰的变量叫做静态变量, 使用 static 修饰的方法叫做静态方法. 静态变量的初始化实在构造函数之前完成的.

static 表述静态成员, 静态成员是属于 class 的而不是实例化的对象, 并且所有对象共享 static 信息. 引用方法 类名.成员名

静态变量

普通的变量都是属于对象的, 类只是一个对象的模板. 静态变量则不同, 他所属于类. 类的的所有对象共享静态变量.

静态方法

使用静态方法需要注意: * 静态方法不能直接引用非静态变量 * 非静态静态方法可以直接引用静态变量

静态常量

静态常量 使用 static 修饰静态变量并 不常见, 最常见的使用 static 修饰静态常量. 静态常量的初始化实在构造函数之前完成的, 并且不能被改变.

public static final int x = 23;

静态语句块的执行实际上是在类加载的时候执行的, 而程序执行之前加载工作就已经完完成了. 所以可以把静态变量的初始化放在静态语句块中, 这样就提前完成它的初始化. 例如:

public class Xxx{
    static int x;
    // static 语句块
    static {
        // 类加载的时候执行此语句, 在构造函数之前
        x = 100; 
    }
}

参数传递

基本类型的参数传递

对象类型的参数传递

java 源文件规范

java 文件中只能有一个 public class ,并且 class 的名字需要和 java文件的名字相同, 且区分大小写;可以有许多非 public 的 class。

class a{ ...
}
class b{ ...
}
public class c{...
}
// 这个文件就叫 c.java

包的使用

java 库是由包组成的, 包是由类组成的. 在一个 java 文件中只能有一个 public 类, 并且这个 public 类的名字必须和包名一致.

导入包

继承

目录

  • 派生类的创建和使用
  • 方法覆写
  • 抽象类的创建和使用
  • 多态和动态绑定
  • Objec 类

派生类

子类就是派生类 父类就是基类就是超级类

继承的使用

// 定义一个基类 Animal
class Animal{
	String name;     // 名字
	String type;     // 种类
	int age;  		// 年龄
	int weight;   // 体重
	void eat(){
		System.out.println("animal eat");
	}
	
	void breath(){
		System.out.println("animal breath");
	}
	
	void sleep(){
		System.out.println("animal sleep");
	}
}

class Tiger extends Animal{
	String tigerType;
	String from;
	void tigerRun(){
		System.out.println("tiger run");
	}
}

子对象的构造

子类的对象是通过从最顶层的基类一层一层向下调用默认构造函数的方式创建的.

无参构造函数

public class extends_structor{
	public static void main(String[] args){
		C c = new C();
	}
}

class A{
	A(){
		System.out.println("class A structor");
	}
}

class B extends A{
	B(){
		System.out.println("class B structor");
	}
}

class C extends B{
	C(){
		System.out.println("class C structor");
	}
}

输出

class A structor
class B structor
class C structor

有参构造函数

继承调用的是默认构造函数, 如果想要调用制定的某个重载的构造函数, 可以通过 super 关键字制定 ```javapublic class extends_structor{ public static void main(String[] args){ System.out.println(“无参调用”); C c = new C(); System.out.println(“有参调用”); C c1 = new C(5); } }

class A{ A(){ System.out.println(“class A structor”); } A( int i){ System.out.println(“调用 A 的有参构造函数 “+i); } }

class B extends A{ B(){ System.out.println(“class B structor”); } B( int i){ super(i); System.out.println(“调用 B 的有参构造函数 “+i); } }

class C extends B{ C(){ System.out.println(“class C structor”); } C( int i){ super(i); System.out.println(“调用 C 的有参构造函数 “+i); } }

输出

无参调用 class A structor class B structor class C structor 有参调用 调用 A 的有参构造函数 5 调用 B 的有参构造函数 5 调用 C 的有参构造函数 5


### 方法的覆写
在子类中提供一个和父类一样的方法, 通过子类对象调用的时候调用的是子类的函数而不是父类的函数, 这就叫方法的覆写.

在子类的 obj 中可以明确的使用 super 关键字调用父类中被覆写的函数
### 多态与动态绑定
多态是指同一个方法根据上下文使用不同定义的能力. java 实现多态有如下几种方式:
* 方法重载
* 继承的时候方法覆写
* 动态绑定

但是 java 中提及多态更多的是和动态绑定一起. 
动态绑定是一种机制, 通过这种机制对一个已经重写的方法的调用将会发生在运行时, 而不是编译时解析.

对象的多态性示例:
``` java
public class extends_dynamic{
	public static void main(String[] args){
		Animal[] animal = new Animal[3];
		animal[0] = new Animal();
		animal[1] = new Tiger();
		animal[2] = new Fish();
		
		animal[0].breath();
		animal[1].breath();
		animal[2].breath();
	}
}

// 定义一个基类 Animal
class Animal{
	String name;     // 名字
	String type;     // 种类
	int age;  		// 年龄
	int weight;   // 体重
	void eat(){
		System.out.println("animal eat");
	}
	
	void breath(){
		System.out.println("animal breath");
	}
	
	void sleep(){
		System.out.println("animal sleep");
	}
}

class Tiger extends Animal{
	String tigerType;
	String from;
	void tigerRun(){
		System.out.println("tiger run");
	}
	
	void breath(){
		System.out.println("老虎是用肺呼吸的");
	}
}

class Fish extends Animal{
	String fishType;
	void swim(){
		System.out.prinln("fish can swim");
	}
	void breath(){
		System.out.println("鱼是用腮呼吸的");
	}
}

输出结果:

animal breath
老虎是用肺呼吸的
鱼是用腮呼吸的

在 java 中对象是多态的, 定义一个 Animal 的对象他既可以保存 Animal 的对象也能保存 Animal 的子类 Tiger 和 Fish 的对象. Tiger 和 Fish 的对象即便是存放在 Animal 的对象变量中, 但是调用 breath 的时候还是会调用的 Tiger 的 breath 和 Fish 的 breath. 这就是动态绑定.

通过 animal[0].swim() 这种方式调用 Fish 的 swim 函数是不行的. 因为 swim 只是在 Fish 中定义没有在 Animal 中定义. 所以通过 Animal 对象变量引用不行, 但可以通过强制类型转换的方式实现

public class extends_dynamic{
	public static void main(String[] args){
		Animal[] animal = new Animal[3];
		animal[0] = new Animal();
		animal[1] = new Tiger();
		animal[2] = new Fish();
		
		for( Animal a: animal){
			if (a instanceof Tiger){
				((Tiger) a).tigerRun();
			} else if(a instanceof Fish){
				((Fish) a).swim();
			} else{
				a.sleep();
			}
		}
	}
}

// 定义一个基类 Animal
class Animal{
	String name;     // 名字
	String type;     // 种类
	int age;  		// 年龄
	int weight;   // 体重
	void eat(){
		System.out.println("animal eat");
	}
	
	void breath(){
		System.out.println("animal breath");
	}
	
	void sleep(){
		System.out.println("animal sleep");
	}
}

class Tiger extends Animal{
	String tigerType;
	String from;
	void tigerRun(){
		System.out.println("tiger run");
	}
	
	void breath(){
		System.out.println("老虎是用肺呼吸的");
	}
}

class Fish extends Animal{
	String fishType;
	void swim(){
		System.out.println("fish can swim");
	}
	void breath(){
		System.out.println("鱼是用腮呼吸的");
	}
}

执行结果

animal sleep
tiger run
fish can swim

final 关键字

当有些类或者类的方法不希望被继承的时候可以在定义的时候使用 final 关键字指定

抽象类

抽象类是指在类中定义方法, 但不去实现它. 而在它的子类中具体实现. 继承抽象类的子类必须父类的抽象方法, 除非子类也是抽象类.

抽象类是使用 abstract 关键字定义的, 例如

public abstract Foo{}

注意 有抽象方法的类一定是抽象类, 但是抽象类中的方法不一定都是抽象方法. 抽象类中也可以实现具体的方法.

下面使用抽象类对 Anima 进行重新定义

public class abstract_class{
	public static void main(String[] args){
		Tiger t = new Tiger();
		Fish f  = new Fish();
		
		t.breath();
		f.breath();
	}
}

// 定义一个基类 Animal
abstract class Animal{
	String name;     // 名字
	String type;     // 种类
	int age;  		// 年龄
	int weight;   // 体重
	void eat(){
		System.out.println("animal eat");
	}
	
	abstract void breath();
	
	void sleep(){
		System.out.println("animal sleep");
	}
}

class Tiger extends Animal{
	String tigerType;
	String from;
	void tigerRun(){
		System.out.println("tiger run");
	}
	
	void breath(){
		System.out.println("老虎是用肺呼吸的");
	}
}

class Fish extends Animal{
	String fishType;
	void swim(){
		System.out.println("fish can swim");
	}
	void breath(){
		System.out.println("鱼是用腮呼吸的");
	}
}

输出

老虎是用肺呼吸的
鱼是用腮呼吸的

抽象类的使用

抽象类不可以实例化, 但是可以定义抽象类的变量, 把抽象类的子类的对象赋值给抽象类的变量. 这样就能通过抽象类的变量调用抽象类中定义的方法了.但要注意这个抽象类的变量只能定义抽象类中定义的方法, 不能调用子类中独有的方法, 除非使用了强制类型转换

Object 类

java 中任何类都是 Object 类的子类. Object 是所有类的基类. 所以一个 Object 变量可以存放任何类型,示例如下:

Object []obj = new Object[3];
Animal a1 = new Tiger();
Animal a2 = new Fish();

obj[0] = a1;
obj[1] = a2;
obj[2] = new String("this is a string");

Object 是所有类的基类, 所以 Object 是没有数据类型表示的, 也就是说 Object 变量表示的所有对象都不知道自己是什么数据类型, 除非使用 instanceof 进行检测, 方能判断出来.

接口和内部类

接口

接口定义了一系列的抽象方法和常量, 形成一个属性集合. 接口可以完以后任何一类都可以实现(叫实现, 不叫继承)接口. 而且一个类可以实现多个接口. 实现接口的类如果不是抽象类就必须要实现接口中定义的所有方法. 可以说接口定义了类的框架, 他实际上是一个完全的抽象类.

接口的定义

接口是用 interface 关键字定义.

修饰符 interface 接口名{
    // 接口内容
    // 声明变量
    类型 变量名;
    ......
    // 声明抽象方法
    返回值类型 方法名(){
        ......
    }
}
  • 接口的定义要注意一下几点:
    • 接口的修饰符只能是默认(不写)或者是 public. 当修饰符是默认时, 接口是包可见的. 在接口所在包之外的类不能使用接口. 修饰符为 public 时, 任何类都可以使用接口.
    • 接口内可以声明变量, 接口内的变量被自动设置为 public static final
    • 接口中定义的方法都是抽象方法, 他们被自动的设置为 public
    • 接口也保存为 .java 文件. 文件名与接口名相同 在接口中声明一个变量 int i; 他的效果和 public static final int i; 相同. 接口定义的例子: ```java public interface Animal{ // 接口变量 int BIG_TYPE = 5;

// 接口中的抽象方法 void sleep(); void eat(); void breath(); }


### 接口的实现
接口的实现是指具体实现接口的类, 实现接口的类的定义形式如下, **一个类可以同时实现多个接口**
```java
class 类名 implements 接口1, 接口2{
    方法1(){}
    方法2(){}
}

实现接口的类必须遵循如下规则:

  • 如果实现接口的类不是抽象类, 那么他必须实现接口的所有方法. 如果实现接口的类是抽象类那么需要在抽象类的子类, 甚至是子类的子类中实现接口的方法
  • 实现接口的方法时, 必须使用相同的方法名和参数列表
  • 实现接口的类的方法必须声明为 public, 因为接口中的所有方法都被定义成了 public 的.

接口使用举例:

public class test{
	public static void main(String[] args){
		Tiger t = new Tiger();
		Fish f  = new Fish();
		
		t.breath();
		f.breath();
	}
}

// 定义一个接口 Animal
public interface Animal{
	// 接口变量
	int BIG_TYPE = 5;
	
	// 接口中的抽象方法
	void sleep();
	void eat();
	void breath();
}

class Tiger implements Animal{
	String tigerType;
	String from;
	
	public void eat(){
		System.out.println("tiger eat");
	}
	
	public void sleep(){
		System.out.println("老虎 sleep");
	}
	
	public void breath(){
		System.out.println("老虎是用肺呼吸的");
	}
}

class Fish implements Animal{
	String fishType;
	public void eat(){
		System.out.println("fish can eat");
	}
	public void breath(){
		System.out.println("鱼是用腮呼吸的");
	}
	
	public void sleep(){
		System.out.println("老虎 sleep");
	}
}

运行结果:

老虎是用肺呼吸的
鱼是用腮呼吸的

接口之间可以有继承关系, 继承接口的接口有他父接口的所有方法. 子接口可以定义自己的方法扩展父接口的功能. 实现这个子接口的类需要实现子接口以及从父接口中继承过来的所有方法.

接口的应用

基于动态绑定的方式使用接口

基类接口的变量可以赋值成实现了接口的子类的对象. 这样就能通过接口变量调用在子类中实现的接口方法. 这个动态绑定特性和类的多态以及动态绑定特性类似.

创建常量组

例如使用 int 表示的星期天数据, 而这些天都是固定不变的, 就可以通过接口来实现:

interface WeekDays{
    int MONDAY = 1;
    int WEDNSDAY =2 
    ......
}

上述接口的定义可以在子列中这样使用

class Time implements WeekDays{
	void print(){
		System.out.println(MONDAY);
		System.out.println(WEDNSDAY);
		......
	}
}

Time 类实现了 WeekDays 接口, 所以可是直接使用 WeekDays 中定义的常量. 把一些固定的常量组放在接口中, 然后在实现接口的类中使用, 这是一个经常使用的编程技巧.

抽象类和接口的比较

抽象类和接口非常相似, 但是他们又不太一样:

  • 一个类可以实现多个接口, 但是只能继承一个抽象类. 可以说接口是 java 中实现多基类继承的一种方式, 但是他也不完全如此.
  • 抽象类中可以有非抽象方法, 即抽象类中可以实现一些方法. 继承抽象类的子列可以对方法进行覆写. 而接口中定义的所有方法都是抽象方法, 不能有非抽象方法
  • 在抽象类中定义的方法可以是 public protect private 也可以是默认, 但是接口中的所有方法都是 public 的
  • 抽象类可以有自己的构造函数, 接口不能.
  • 抽象类和接口都不能实例化, 但可以通过他们的变量保存子类对象或实现类的对象. 可以说他们都能实现多态

内部类

所谓内部类就是在一个类的内部再定义类.内部类所在的类叫做宿主类.

内部类的定义

class Outer{
	String out_string = "out class string";
	class iner{
		System.out.println(out_string);
	}
}

上述示例可知, 内部类中是可以访问”外部类”中定义的变量的.

静态内部类和非静态内部类

内部类分为两种: 静态的和非静态的.静态内部类可以调用宿主类的所有成员变量和方法, 并且像宿主类的非静态成员一样引用他们. 静态内部类是使用 static 修饰的类, 静态内部类不能直接访问起宿主类的成员, 而必须通过对象才能访问.

局部内部类

内部类不仅可以在类中定义, 也可以在方法中定义. 变量如果定义在类中就叫做成员变量, 如果是定义在方法中就叫做局部变量. 类也是一样, 定义在方法中的类就叫做局部内部类.

java 包管理介绍

Packages

Creating and Using Packages

Naming a Package

Using Package Members

Importing a Package Member

To import a specific member into the current file, put an import statement at the beginning of the file before any type definitions but after the package statement, if there is one. Here’s how you would import the Rectangle class from the graphics package created in the previous section.

import graphics.Rectangle; Now you can refer to the Rectangle class by its simple name.

Rectangle myRectangle = new Rectangle();

Importing an Entire Package

o import all the types contained in a particular package, use the import statement with the asterisk (*) wildcard character.

import graphics.*;

Now you can refer to any class or interface in the graphics package by its simple name.

Circle myCircle = new Circle();
Rectangle myRectangle = new Rectangle();
import graphics.Rectangle;
import graphics.Rectangle.*;

Be aware that the second import statement will not import Rectangle.

The Static Import Statement

There are situations where you need frequent access to static final fields (constants) and static methods from one or two classes. Prefixing the name of these classes over and over can result in cluttered code. The static import statement gives you a way to import the constants and static methods that you want to use so that you do not need to prefix the name of their class.

The java.lang.Math class defines the PI constant and many static methods, including methods for calculating sines, cosines, tangents, square roots, maxima, minima, exponents, and many more. For example,

public static final double PI 
    = 3.141592653589793;
public static double cos(double a)
{
    ...
}

Ordinarily, to use these objects from another class, you prefix the class name, as follows.

double r = Math.cos(Math.PI * theta);

You can use the static import statement to import the static members of java.lang.Math so that you don’t need to prefix the class name, Math. The static members of Math can be imported either individually:

import static java.lang.Math.PI;

or as a group:

import static java.lang.Math.*;

Once they have been imported, the static members can be used without qualification. For example, the previous code snippet would become:

double r = cos(PI * theta);

Obviously, you can write your own classes that contain constants and static methods that you use frequently, and then use the static import statement. For example,

import static mypackage.MyConstants.*;

Managing Source and Class Files

异常处理

异常基本知识

java 中所有异常类都是内置类 Throwable 的子类. Throwable 有两个子类:

  • Exception
    • IOException
    • RuntimeException
  • Error

Error 分支它定义了 java 运行时的内部错误. 通过 Error 指明与运行环境相关的错误, 应用程序不应该抛出这类异常, 发生这类异常通常是无法处理的.

Exception 它用于应用程序应该捕获的异常.

异常的使用

捕获异常

public class Exception_test{
	public static void main(String[] args){
		String str = null;
		int strLen = 0;
		try{
			strLen = str.length();
		} catch(NullPointerException e){
			System.out.println("获取字符串长度时发生异常: " +e);
		}
	}
}
// 输出
// 获取字符串长度时发生异常: java.lang.NullPointerException

一个 try 可以对应多个 catch, 例如:

try{
} catch (xxx e){
} catch (xxx e){
}

printStackTrace

使用 printStackTrace 打印异常堆栈

public class Exception_test{
	public static void main(String[] args){
		String str = null;
		int strLen = 0;
		try{
			strLen = str.length();
		} catch(NullPointerException e){
			System.out.println("获取字符串长度时发生异常: " +e);
			e.printStackTrace();
		}
	}
}

运行结果:

获取字符串长度时发生异常: java.lang.NullPointerException
java.lang.NullPointerException
	at Exception_test.main(Exception_test.java:6)

finally

public class Exception_test{
	public static void main(String[] args){
		String str = null;
		int strLen = 0;
		try{
			strLen = str.length();
			System.out.println("异常语句后面的代码");
		} catch(NullPointerException e){
			System.out.println("获取字符串长度时发生异常: " +e);
			//e.printStackTrace();
		}
		
		System.out.println("catch 块后面的代码");
	}
}

上述代码的运行结果如下:

获取字符串长度时发生异常: java.lang.NullPointerException
catch 块后面的代码

可以看到 System.out.println("异常语句后面的代码"); 这句并没有执行. 在 java 中就是这样, 当遇到异常之后就会直接跳到 catch 语句, catch 结束后直接向后执行.为了能让异常点后面的代码可以继续执行 java 提供了 finally 语句

public class Exception_test{
	public static void main(String[] args){
		String str = null;
		int strLen = 0;
		try{
			strLen = str.length();
			System.out.println("异常语句后面的代码");
		} catch(NullPointerException e){
			System.out.println("获取字符串长度时发生异常: " +e);
			//e.printStackTrace();
		} finally{
			System.out.println("无论是否发生异常, 此处都会执行");
		}
		
		System.out.println("catch 块后面的代码");
	}
}

执行结果:

获取字符串长度时发生异常: java.lang.NullPointerException
无论是否发生异常, 此处都会执行
catch 块后面的代码
  • catch 语句块可以有多个, 但 finally 只能有一个

方法抛出异常

  • 通过 throws 抛出异常
  • 使用 throw 抛出异常
  • 非检查异常和检查异常用 throws 和 throw 的区别 对于未检查异常可以不用 throws 声明直接使用 throw 抛出, 而检查以后必须使用 throws 声明后才能使用 throw 抛出