LastPoem / Restart

2 stars 0 forks source link

Java基础 #37

Open LastPoem opened 4 years ago

LastPoem commented 4 years ago

Java基础语法

大小写敏感 Java是大小写敏感的 类名 所有类名的首字母应该大写。如果类名由若干个单词组成,那么每个单词首字母都应该大写(大驼峰) 方法名 所有方法名都应该小写字母开头,多个单词则后边的单词开头大写(小驼峰) 源文件名 源文件名必须和类名相同,文件后缀为.java

标识符 类名、变量名、方法名都被称为标识符

修饰符 Java可以用修饰符来修饰类中的方法和属性,主要有两类修饰符:

  1. 访问控制修饰符:default, public, protected, private
  2. 非访问控制修饰符:final, abstract, static, synchronized

Java变量主要有以下几种类型

  1. 局部变量
  2. 类变量(静态变量)
  3. 成员变量(非静态变量)

继承 一个类可以由其它类派生。利用继承的方法,可以重用已存在的类的方法和属性。派生类为子类,被继承的类叫超类

接口 Java中的接口可理解为对象间相互通信的协议。接口只定义派生要用到的方法,但方法的具体实现完全取决于派生类

LastPoem commented 4 years ago

Java对象和类

对象是类的一个实例,有状态和行为,对象是具体的。例如一个人是个对象,他有姓名性别年龄,行为有工作睡觉等。 是一个模板,它描述了一类对象的行为和状态。如人类描述了所有人。

类可以看做创建Java对象的模板。

如:

public class Dog{
  String breed;
  int age;
  String color;
  void barking() {}
  void hungry() {}
  void sleeping() {}
}

一个类可以包含以下类型变量: 局部变量:在方法,构造方法或者语句块中定义的变量被称为局部变量。变量的声明和初始化都是在方法中,方法结束后变量就会自动销毁。 成员变量:成员变量定义在类中,是方法体外的变量。这种变量在创建对象的时候实例化,可以被类中方法,构造方法和特定类的语句块访问。 类变量:类变量也声明在类中,方法体之外。但必须声明为static类型。

构造方法: 每个类都有构造方法。如果没显示定义类的构造方法,Java编译器会为该类自动提供一个默认构造方法。 一个构造方法示例:

public class Puppy{
  public Puppy() {} 
  public Puppy(String name) {}
}

创建对象 对象是根据类创建的。使用关键字new来创建一个新对象。需要三步

  1. 声明:声明一个对象,包括对象名和对象类型
  2. 实例化:使用new关键字创建一个对象
  3. 初始化:使用new创建对象时,会调用构造方法初始化对象 一个创建对象的例子
    
    public class Puppy{
    public Puppy(String name) {
    // 这个构造器只有一个参数name
    System.out.println("小狗名字是:"+name);
    }
    public static void main(String[] args) {
    Puppy myPuppy = new Puppy("Tom");
    }

}


**访问实例变量和方法**
通过已创建的对象来访问成员变量和成员方法,和C++类似

/ 实例化对象 / Object referenceVariable = new Constructor(); / 访问类中的变量 / referenceVariable.variableName; / 访问类中的方法 / referenceVariable.methodName();

实例如下

public class Puppy{ int puppyAge; public Puppy(String name){ // 这个构造器仅有一个参数:name System.out.println("小狗的名字是 : " + name ); }

public void setAge( int age ){ puppyAge = age; }

public int getAge( ){ System.out.println("小狗的年龄为 : " + puppyAge ); return puppyAge; }

public static void main(String[] args){ / 创建对象 / Puppy myPuppy = new Puppy( "tommy" ); / 通过方法来设定age / myPuppy.setAge( 2 ); / 调用另一个方法获取age / myPuppy.getAge( ); /你也可以像下面这样访问成员变量 / System.out.println("变量值 : " + myPuppy.puppyAge ); } }



**源文件声明规则**
- 一个源文件中只能有一个public类
- 源文件名称应该和public类名保持一致,如源文件中public类名为Employee,则源文件名为Employee.java
- 如果一个类定义在某个包中,那么package语句应该在源文件首行
- 若源文件包含import语句,应放在package语句和类定义之间,没有import语句则放在开头
- import 语句和package语句对源文件中定义的所有类都有效。在同一源文件中,不能给 不同的类不同的包声明。

**Java包**
包主要用来对类和接口进行分类。
**import语句**
在Java中,如果给出一个完整的限定名,包括包名类名,编译器就能很容易定位到源代码或类。import语句就是让编译器知道去哪找到某个类。

一些笔记:
由于Java强制要求类名(唯一的public类)和文件名统一,在引用其他类时就无需显式声明。编译器会根据类名寻找同名文件。

package作用就相当于c++中的namespace,防止名字相同的类产生冲突。其实就是文件夹,这个文件夹里放的都是同一类的东西。但是把这种文件夹叫做包。包名全部小写。

为何Java源文件中只能有一个Public类?Java程序是从一个public类里的main函数开始执行的,就像C语言中的main函数一样。只能有一个public类是为了给类装载器提供方便。

成员变量和类变量的区别:
由static修饰的变量是静态变量,实质上就是一个全局变量。如果某个内容被所有对象共享,就用static修饰。
1.两个变量声明周期不同。
成员变量随对象创建而存在,对象回收后就释放。
静态变量随着类的加载存在,随着类的消失而消失。

2.调用方式不同
成员变量只能被对象调用,静态变量可以被对象也可以被类名调用。

3.别名不同
成员变量也成实例变量,静态变量又叫类变量。

4.数据存储位置不同
成员变量存储在堆内存的对象中,所以也叫对象的特有数据
静态变量数据存储在方法区的静态区,也叫对象的共享数据。
LastPoem commented 4 years ago

Java基本数据类型

变量是申请内存来存储值。当创建变量时,需要在内存中申请空间。 内存管理系统根据变量类型为变量分配存储空间,分配的空间只能用来存储该类型的数据。

Java的两大数据类型: 内置数据类型和引用数据类型。

Java提供了八中基本类型:六种数字类型,一种字符类型,和一种布尔型。 byte short int long float double boolean char

引用类型 Java中引用类型的变量类似于C++中的指针。引用类型指向一个对象,指向对象的变量是引用变量。这些变量是在声明时被指定为一个特定类型,一旦声明就无法改变。 对象和数组都是引用数据类型 所有引用类型的默认值都是null 一个引用变量可以用来引用任何与之兼容的类型

Java常量 常量在程序运行时不能被修改 用final关键字来修饰常量。声明方式和变量类似。通常用大写字母表示常量。

自动类型转换 运算中不同类型数据先转化为同一类型再进行运算。 数据类型必须满足规则:

  1. 不能对boolean类型进行类型转换。
  2. 不能把对象类型转换成不相关类的对象。
  3. 在把容量大的类型转换为容量小的类型时必须使用强制类型转换。
  4. 转换过程中可能导致溢出或损失精度,例如:
    int i =128;   
    byte b = (byte)i;

    因为 byte 类型是 8 位,最大值为127,所以当 int 强制转换为 byte 类型时,值 128 时候就会导致溢出。

  5. 浮点数到整数的转换是通过舍弃小数得到,而不是四舍五入,例如:
    (int)23.7 == 23;        
    (int)-45.89f == -45

    必须满足转换前的数据类型的位数要低于转换后的数据类型,例如: short数据类型的位数为16位,就可以自动转换位数为32的int类型,同样float数据类型的位数为32,可以自动转换为64位的double类型。

强制类型转换 条件是转换的数据类型必须是兼容的 格式:(type)value type

int i1 = 123; 
byte b = (byte)i1
LastPoem commented 4 years ago

Java变量类型

在Java中,所有变量在使用前必须声明。以下为一些变量声明实例。

int a, b, c;         // 声明三个int型整数:a、 b、c
int d = 3, e = 4, f = 5; // 声明三个整数并赋予初值
byte z = 22;         // 声明并初始化 z
String s = "runoob";  // 声明并初始化字符串 s
double pi = 3.14159; // 声明了双精度浮点型变量 pi
char x = 'x';        // 声明变量 x 的值是字符 'x'。

Java支持的变量类型有:

  1. 类变量:独立于方法之外的变量,用 static 修饰。
  2. 实例变量:独立于方法之外的变量,不过没有 static 修饰。
  3. 局部变量:类的方法中的变量。

局部变量

实例变量

类变量(静态变量) 也称静态变量,在类中以static关键字声明,必须在方法之外。 无论一个类创建了多少个对象,类只拥有类变量的一份拷贝 静态变量除了被声明为常量外很少使用。常量是指声明为public/private,final和static类型的变量。常量初始化后不可改变 静态变量在第一次被访问时创建,在程序结束时销毁 与实例变量有相似的可见性。但为了对类的使用者可见,大多数静态变量声明为public类型 默认值和实例变量相似 静态变量可通过ClassName.VariableName的方式访问

LastPoem commented 4 years ago

Java修饰符

主要分为两类: 访问修饰符和非访问修饰符

修饰符用来定义类、方法或变量,通常放在语句最前端。

public class ClassName {
   // ...
}
private boolean myFlag;
static final double weeks = 9.5;
protected static final int BOXWIDTH = 42;
public static void main(String[] arguments) {
   // 方法体
}

访问控制修饰符 Java中可使用访问控制符来保护对类、变量、方法和构造方法的访问。Java支持4种不同的访问权限

  1. default 默认,什么都不写。在同一包内可见,不使用任何修饰符。使用对象:类 接口 变量 方法
  2. private 在同一类内可见。使用对象:变量 方法。注意: 不能修饰类(外部类)
  3. public 对所有类可见。使用对象:类 接口 变量 方法
  4. protected 对同一包内的类和所有子类可见。使用对象:变量 方法。注意:不能修饰类(外部类)
修饰符 当前类 同一包内 子孙类(同一包) 子孙类(不同包) 其他包
public Y Y Y Y Y
protected Y Y Y Y/N N
default Y Y Y N N
private Y N N N N

默认访问修饰符-不使用任何关键字。 对同一包内的类是可见的。接口的变量都隐式声明为public static final, 而接口里的方法默认访问权限为public。

私有访问修饰符-private 私有访问修饰符是最严格的访问级别,所以被声明为private的方法,变量和构造方法只能被所属类访问。并且类和接口不能声明为private。声明为私有访问类型的变量只能通过类中公共的getter方法被外部类访问。 private访问修饰符的使用主要用来隐藏类的实现细节和保护类的数据。

public class Logger {
   private String format;
   public String getFormat() {
      return this.format;
   }
   public void setFormat(String format) {
      this.format = format;
   }
}

以上代码中,Logger类中的format变量为私有变量,所以其它类不能直接得到和设置该变量值。为了使其它类可以操作该变量,定义了两个public方法返回和设置值。

公有访问修饰符-public 被声明为public的类 方法 构造方法和接口能被任何其它类访问。 如果几个相互访问的public类分布在不同包中,则需要导入相应public类所在的包。由于类的继承性,类的所有公共方法和变量都被其子类继承。

受保护的访问修饰符-protected protected需要从两个点来分析说明: 子类与基类在同一包中: 被声明为protected的变量 方法和构造器能被同一个包中的任何其它类访问 子类与基类不在同一包中: 那么在子类中,子类实例可以访问其从基类继承而来的protected方法,而不能访问基类实例的protected方法。 protected可以修饰数据成员,构造方法,方法成员,不能修饰类(内部类除外) 接口及接口的成员变量和成员方法不能声明为protected。 子类能访问protected修饰符声明的方法和变量,这样就能保护不相关的类使用它们。

访问控制和继承

非访问修饰符

static修饰符 静态变量 static关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。静态变量又称类变量,局部变量不能被声明为static变量。

静态方法 static关键字用来声明独立于对象的静态方法,静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据。 对类变量和方法的访问可以直接使用 classname.variablename 和 classname.methodname 的方式访问。

final修饰符 final变量 final表示“最后的“,一旦赋值后不能被重新赋值。被final修饰的实例变量必须显式指定初始值。 final修饰符通常和static修饰符一起用来创建类常量。

final方法 父类中的final方法可以被子类继承,但不能被子类重写。

final类 final类不能被继承。

abstract修饰符 抽象类 抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充。 一个类不能同时被abstract和final修饰。如果一个类包含了抽象方法,该类一定要声明为抽象类。

abstract class Caravan{
   private double price;
   private String model;
   private String year;
   public abstract void goFast(); //抽象方法
   public abstract void changeColor();
}

抽象方法 抽象方法是一种给没有任何实现的方法,它的具体实现由子类提供。 抽象方法不能被声明为final和static。 任何继承抽象类的子类必须实现父类的所有抽象方法,除非这个子类也是抽象类。 如果一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法。 抽象方法的声明以分号结尾

public abstract class SuperClass{
    abstract void m(); //抽象方法
}

class SubClass extends SuperClass{
     //实现抽象方法
      void m(){
          .........
      }
}

synchronized修饰符 被修饰的方法同一时间只能被一个线程访问。synchronized修饰符可以应用于四个访问修饰符。

transient修饰符 序列化的对象包含被transient修饰的实例变量时,Java虚拟机(JVM)跳过该特定的变量. 该修饰符包含在定义变量的语句中,用来预处理类和变量的数据类型。

volatile修饰符 volatile修饰符的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。当成员变量发生变化时会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同线程总是看到某个成员变量的同一个值。 public class MyRunnable implements Runnable

{
    private volatile boolean active;
    public void run()
    {
        active = true;
        while (active) // 第一行
        {
            // 代码
        }
    }
    public void stop()
    {
        active = false; // 第二行
    }
}

通常情况下,在一个线程调用 run() 方法(在 Runnable 开启的线程),在另一个线程调用 stop() 方法。 如果 第一行 中缓冲区的 active 值被使用,那么在 第二行 的 active 值为 false 时循环不会停止。 但是以上代码中我们使用了 volatile 修饰 active,所以该循环会停止。

LastPoem commented 4 years ago

Java运算符

分为几组:

算术运算符 包括 + - * / % ++ --

前置自增自减++a --a 先进行自增或自减,再进行表达式运算。后置则相反。

关系运算符 == != > < >= <=

位运算符 位运算符应用于整数类型,长整型,短整型,字符型,和字节型等。位运算符作用在所有的位上,并且按位运算。

操作符 描述 例子
如果相对应位都是1,则结果为1,否则为0 (A&B),得到12,即0000 1100
| 如果相对应位都是 0,则结果为 0,否则为 1 (A | B)得到61,即 0011 1101
^ 如果相对应位值相同,则结果为0,否则为1 (A ^ B)得到49,即 0011 0001
按位取反运算符翻转操作数的每一位,即0变成1,1变成0。 (〜A)得到-61,即1100 0011
<< 按位左移运算符。左操作数按位左移右操作数指定的位数。 A << 2得到240,即 1111 0000
以及>> 按位右移运算符。左操作数按位右移右操作数指定的位数。 A >> 2得到15即 1111
以及>>> 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。 A>>>2得到15即

逻辑运算符

操作符 描述 例子
&& 称为逻辑与运算符。当且仅当两个操作数都为真,条件才为真。 (A && B)为假。
| | 称为逻辑或操作符。如果任何两个操作数任何一个为真,条件为真。 (A | | B)为真。
称为逻辑非运算符。用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算符将得到false。 !(A && B)为真。

短路逻辑运算符 当使用与逻辑运算符时,两个操作数都为true时结果才为true。但当得到第一个操作为false时就不会再判断第二个操作了。

赋值运算符

操作符 描述 例子
。= 简单的赋值运算符,将右操作数的值赋给左侧操作数 C = A + B将把A + B得到的值赋给C
。+ = 加和赋值操作符,它把左操作数和右操作数相加赋值给左操作数 C + = A等价于C = C + A
。- = 减和赋值操作符,它把左操作数和右操作数相减赋值给左操作数 C - = A等价于C = C - A
。* = 乘和赋值操作符,它把左操作数和右操作数相乘赋值给左操作数 C = A等价于C = C A
。/ = 除和赋值操作符,它把左操作数和右操作数相除赋值给左操作数 C / = A,C 与 A 同类型时等价于 C = C / A
。(%)= 取模和赋值操作符,它把左操作数和右操作数取模后赋值给左操作数 C%= A等价于C = C%A
。<< = 左移位赋值运算符 C << = 2等价于C = C << 2
。>> = 右移位赋值运算符 C >> = 2等价于C = C >> 2
。&= 按位与赋值运算符 C&= 2等价于C = C&2
。^ = 按位异或赋值操作符 C ^ = 2等价于C = C ^ 2
。| = 按位或赋值操作符 C | = 2等价于C = C | 2

条件运算符(?:) 三元运算符。 variable x = (expression) ? value if true : value if false

instanceof运算符 用于操作对象实例,检查该对象是否是一个特定类型,类或接口 ( Object reference variable ) instanceof (class/interface type) 若左侧变量所指的对象是右侧类或接口的一个对象,结果就为true

运算符优先级

类别 操作符 关联性
后缀 () [] . (点操作符) 左到右
一元 expr++ expr-- 从左到右
一元 ++expr --expr + - ~ ! 从右到左
乘性 * /% 左到右
加性 + - 左到右
移位 >> >>>  << 左到右
关系 > >= < <= 左到右
相等 ==  != 左到右
按位与 左到右
按位异或 ^ 左到右
按位或 | 左到右
逻辑与 && 左到右
逻辑或 | | 左到右
条件 ?: 从右到左
赋值 = + = - = * = / =%= >> = << =&= ^ = | = 从右到左
逗号 左到右
LastPoem commented 4 years ago

Java循环结构

主要有三种

while(布尔表达式){
      //循环内容
}

do {
       //代码语句
}while(布尔表达式);

for(初始化; 布尔表达式; 更新) {
    //代码语句
}

Java增强for循环 Java5引入了一种主要用于数组的增强型for循环

for(声明语句 : 表达式)
{
   //代码句子
}

声明语句:声明新的局部变量,该变量类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。 表达式:表达式是要访问的数组名,或者是返回值为数组的方法。

public class Test {
   public static void main(String args[]){
      int [] numbers = {10, 20, 30, 40, 50};

      for(int x : numbers ){
         System.out.print( x );
         System.out.print(",");
      }
      System.out.print("\n");
      String [] names ={"James", "Larry", "Tom", "Lacy"};
      for( String name : names ) {
         System.out.print( name );
         System.out.print(",");
      }
   }
}

以上代码结果: 10,20,30,40,50, James,Larry,Tom,Lacy,

break关键字 break主要用在循环语句或switch语句中,用来跳出整个语句块。break跳出最里层的循环,并且继续执行该循环下面的语句。

continue关键字 continue适用于任何循环控制结构中,作用是让程序立刻跳转到下一次循环的迭代。 在for循环中,continue语句使程序立即跳转到布尔表达式的判断语句。 在while或do...while中,程序立即跳转到布尔表达式的判断语句。

LastPoem commented 4 years ago

Java条件语句

if语句,if...else语句,if...else if...else语句

switch case switch case判断一个变量和一系列值中某个值是否相等,每个值称为一个分支。 switch case语句语法格式如下:

switch(expression){
    case value :
       //语句
       break; //可选
    case value :
       //语句
       break; //可选
    //你可以有任意数量的case语句
    default : //可选
       //语句
}
LastPoem commented 4 years ago

Java Number & Math类

一般,当需要使用数字时,通常使用内置数据类型如byte,int,long,double等。 但开发中经常需要使用对象而不是内置数据类型的情形。因此Java为每个内置数据类型提供了对应的包装类。

包装类 基本数据类型
Boolean boolean
Byte byte
Short short
Integer int
Long long
Character char
Float float
Double double

(Integer、Long、Byte、Double、Float、Short)都是抽象类 Number 的子类。 包装类的关系

这种由编译器特别支持的包装称为装箱,所以当内置数据类型被当作对象使用的时候,编译器会把内置类型装箱为包装类。相似的,编译器也可以把一个对象拆箱为内置类型。Number 类属于 java.lang 包。

Java Math 类 Java的Math类包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数。 Math的方法都被定义为static形视,通过Math类可以在主函数中直接调用。

Number & Math类方法

Java Character类

Character类用于对单个字符进行操作。 Character类在对象中包装一个基本类型char的值。 Character ch = new Character('a');

转义

转义序列 描述
\t 在文中该处插入一个tab键
\b 在文中该处插入一个后退键
\n 在文中该处换行
\r 在文中该处插入回车
\f 在文中该处插入换页符
\' 在文中该处插入单引号
\" 在文中该处插入双引号
\\ 在文中该处插入反斜杠

Java String类

String greeting = "菜鸟教程";

注意: String类是不可改变的。一旦创建了String对象,值就无法改变了。如果需要对字符串做很多修改,那么应该选择使用StringBuffer & StringBuilder类。

Java StringBuffer 和 StringBuilder 类

这两个类的对象可以被多次修改,并且不产生新的未使用对象。 StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

public class Test{
  public static void main(String args[]){
    StringBuffer sBuffer = new StringBuffer("菜鸟教程官网:");
    sBuffer.append("www");
    sBuffer.append(".runoob");
    sBuffer.append(".com");
    System.out.println(sBuffer);  
  }
}
LastPoem commented 4 years ago

Java数组

Java中的数组用来存储固定大小的同类型元素。

首先必须声明数组变量,才能在程序中使用数组。

double[] myList; // 首选的方法 或 double myList[]; // 效果相同,但不是首选方法

创建数组 arrayRefVar = new dataType[arraySize];

声明和创建用一条语句表示: dataType[] arrayRefVar = new dataType[arraySize];

dataType[] arrayRefVar = {value0, value1, ..., valuek};

For-Each循环 可以在不使用下标的情况下遍历数组。

for(type element: array)
{
    System.out.println(element);
}

实例

public class TestArray {
   public static void main(String[] args) {
      double[] myList = {1.9, 2.9, 3.4, 3.5};

      // 打印所有数组元素
      for (double element: myList) {
         System.out.println(element);
      }
   }
}

数组可以作为函数参数和函数返回值。

Array类 java.util.Arrays 类能方便地操作数组,它提供的所有方法都是静态的。 具有以下功能:

给数组赋值:通过 fill 方法。 对数组排序:通过 sort 方法,按升序。 比较数组:通过 equals 方法比较数组中元素值是否相等。 查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作。

序号 方法和说明
1 public static int binarySearch(Object[] a, Object key)用二分查找算法在给定数组中搜索给定值的对象(Byte,Int,double等)。数组在调用前必须排序好的。如果查找值包含在数组中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。
2 public static boolean equals(long[] a, long[] a2)如果两个指定的 long 型数组彼此相等,则返回 true。如果两个数组包含相同数量的元素,并且两个数组中的所有相应元素对都是相等的,则认为这两个数组是相等的。换句话说,如果两个数组以相同顺序包含相同的元素,则两个数组是相等的。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。
3 public static void fill(int[] a, int val)将指定的 int 值分配给指定 int 型数组指定范围中的每个元素。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。
4 public static void sort(Object[] a)对指定对象数组根据其元素的自然顺序进行升序排列。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。
LastPoem commented 4 years ago

Java日期时间

java.util包提供了Date类来封装当前日期和时间。Date类提供了两个构造函数来实例化Date对象。 第一个构造函数使用当前日期和时间来初始化对象。 Date( ) 第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数。 Date(long millisec) 获取当前日期时间:

import java.util.Date;

public class DateDemo {
   public static void main(String args[]) {
       // 初始化 Date 对象
       Date date = new Date();

       // 使用 toString() 函数显示日期时间
       System.out.println(date.toString());
   }
}

日期比较 Java使用以下三种方法来比较两个日期:

使用 getTime() 方法获取两个日期(自1970年1月1日经历的毫秒数值),然后比较这两个值。 使用方法 before(),after() 和 equals()。例如,一个月的12号比18号早,则 new Date(99, 2, 12).before(new Date (99, 2, 18)) 返回true。 使用 compareTo() 方法,它是由 Comparable 接口定义的,Date 类实现了这个接口。

import  java.util.*;
import java.text.*;

public class DateDemo {
   public static void main(String args[]) {

      Date dNow = new Date( );
      SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");

      System.out.println("当前时间为: " + ft.format(dNow));
   }
}

SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss"); 这一行代码确立了转换的格式,其中 yyyy 是完整的公元年,MM 是月份,dd 是日期,HH:mm:ss 是时、分、秒。 注意:有的格式大写,有的格式小写,例如 MM 是月份,mm 是分;HH 是 24 小时制,而 hh 是 12 小时制。

可以使用printf格式化日期时间 SimpleDateFormat 类有一些附加的方法,特别是parse(),它试图按照给定的SimpleDateFormat 对象的格式化存储来解析字符串。

Java休眠(sleep) sleep()使当前线程进入停滞状态(阻塞当前线程),让出CPU的使用,目的是不让当前线程独自霸占该进程所获得CPU资源,以留一定时间给其它线程执行的机会。

Calendar类 如何才能设置和获取日期数据的特定部分呢,比如说小时,日,或者分钟? 我们又如何在日期的这些部分加上或者减去值呢? 答案是使用Calendar 类。 Calendar类的功能要比Date类强大很多,而且在实现方式上也比Date类要复杂一些。 Calendar类是一个抽象类,在实际使用时实现特定的子类的对象,创建对象的过程对程序员来说是透明的,只需要使用getInstance方法创建即可。

Calendar c = Calendar.getInstance();//默认是当前日期 //创建一个代表2009年6月12日的Calendar对象 Calendar c1 = Calendar.getInstance(); c1.set(2009, 6 - 1, 12);

常量 描述
Calendar.YEAR 年份
Calendar.MONTH 月份
Calendar.DATE 日期
Calendar.DAY_OF_MONTH 日期,和上面的字段意义完全相同
Calendar.HOUR 12小时制的小时
Calendar.HOUR_OF_DAY 24小时制的小时
Calendar.MINUTE 分钟
Calendar.SECOND
Calendar.DAY_OF_WEEK 星期几

Calendar的月份从0开始,在实际使用中要注意这点。

LastPoem commented 4 years ago

Java正则表达式

正则表达式定义了字符串的模式 一个字符串其实就是一个简单的正则表达式。 java.util.regex 包主要包括以下三个类:

Pattern 类: pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。

Matcher 类: Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。

PatternSyntaxException: PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。

import java.util.regex.*;

class RegexExample1{
   public static void main(String args[]){
      String content = "I am noob " +
        "from runoob.com.";

      String pattern = ".*runoob.*";

      boolean isMatch = Pattern.matches(pattern, content);
      System.out.println("字符串中是否包含了 'runoob' 子字符串? " + isMatch);
   }
}
//实例输出结果为:
//字符串中是否包含了 'runoob' 子字符串? true

捕获组 捕获组是把多个字符当一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。 例如,正则表达式(dog)创建了单一分组,组里包含“d”,"o",“g” 捕获组是通过从左至右计算其开括号来编号。例如,在表达式((A)(B(C))),有四个这样的组:

((A)(B(C))) (A) (B(C)) (C) 可以通过调用 matcher 对象的 groupCount 方法来查看表达式有多少个分组。groupCount 方法返回一个 int 值,表示matcher对象当前有多个捕获组。

还有一个特殊的组(group(0)),它总是代表整个表达式。该组不包括在 groupCount 的返回值中。

正则表达式语法

//例如检验QQ号,要求必须是5-15位数字,不能以0开头
public class regex {
    public static void main(String[] args) {
            checkQQ2("0123134");
    }
    public static void checkQQ2(String qq) {                                                            
            String reg = "[1-9][0-9]{4,14}";                  
            System.out.println(qq.matches(reg)?"合法qq":"非法qq");                                 
    }
}
//小括号分组:数左边的小括号第几个就是第几组
Pattern p = Pattern.compile("(\\d{2})([a-z]{2,3})");
Matcher m =p.matcher("33aa-32sdy-29ssc");
while(m.find()) {
   System.out.println(m.group(2));//每次匹配获取第二组内容
}
/*
结果:
aa
sdy
ssc
*/

//向前引用:
Pattern p = Pattern.compile("(\\d(\\d))\\2");
 Matcher matcher = p.matcher("211");
 System.out.println(matcher.matches());
//结果:true
//解释:"\\2"代表引用前面的第2组匹配的值
LastPoem commented 4 years ago

Java方法

Java方法是语句的集合,它们在一起执行一个功能。

方法是解决一类问题的步骤的有序组合 方法包含于类或对象中 方法在程序中被创建,在其他地方被引用 方法的优点

  1. 使程序变得更简短而清晰。
  2. 有利于程序维护。
  3. 可以提高程序开发的效率。
  4. 提高了代码的重用性。 方法的命名规则 1.方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头写,不使用连接符。例如:addPerson。 2.下划线可能出现在 JUnit 测试方法名称中用以分隔名称的逻辑组件。一个典型的模式是:test_,例如 testPop_emptyStack。

一般情况下,定义一个方法包含以下语法:

修饰符 返回值类型 方法名(参数类型 参数名){
    ...
    方法体
    ...
    return 返回值;
}

方法包含一个方法头和一个方法体。下面是一个方法的所有部分:

修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。 返回值类型 :方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。 方法体:方法体包含具体的语句,定义该方法的功能。 12-130Q1220955916

方法调用 当方法有返回值的时候,方法通常被当做一个值。 当方法返回值为void,方法调用一定是一条语句。

方法重载 创建有相同名字但参数不同的方法

变量作用域

变量范围是程序中该变量可以被引用的部分。 方法内定义的变量被称为局部变量。 局部变量作用范围从声明开始,直到包含它的块结束。必须声明才能使用。 而参数的方法涵盖整个方法,参数实际上是一个局部变量。 for循环的初始化部分声明的变量,其作用范围在整个循环。但循环体内声明的变量范围是从它声明到循环体结束。

构造方法 当一个对象被创建的时候,构造方法用来初始化对象。构造方法和它所在类名相同,但构造方法没有返回值。 通常会使用构造方法给一个类的实例变量赋初值,或者执行其它必要的步骤来创建一个完整的对象。 不管你是否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个默认构造方法,默认构造方法的访问修改符和类的访问修改符相同(类为 public,构造函数也为 public;类改为 protected,构造函数也改为 protected)。 一旦你定义了自己的构造方法,默认构造方法就会失效。

可变参数 方法的可变参数的声明如下所示:

typeName... parameterName 在方法声明中,在指定参数类型后加一个省略号(...) 。 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。

public class VarargsDemo {
    public static void main(String args[]) {
        // 调用可变参数的方法
        printMax(34, 3, 3, 2, 56.5);
        printMax(new double[]{1, 2, 3});
    }

    public static void printMax( double... numbers) {
        if (numbers.length == 0) {
            System.out.println("No argument passed");
            return;
        }

        double result = numbers[0];

        for (int i = 1; i <  numbers.length; i++){
            if (numbers[i] >  result) {
                result = numbers[i];
            }
        }
        System.out.println("The max value is " + result);
    }
}

finalize() 方法 Java 允许定义这样的方法,它在对象被垃圾收集器析构(回收)之前调用,这个方法叫做 finalize( ),它用来清除回收对象。 例如,你可以使用 finalize() 来确保一个对象打开的文件被关闭了。 在 finalize() 方法里,你必须指定在对象销毁时候要执行的操作。 finalize() 一般格式是:

protected void finalize()
{
   // 在这里终结代码
}

关键字 protected 是一个限定符,它确保 finalize() 方法不会被该类以外的代码调用。 当然,Java 的内存回收可以由 JVM 来自动完成。如果你手动使用,则可以使用上面的方法。 实例

public class FinalizationDemo {  
  public static void main(String[] args) {  
    Cake c1 = new Cake(1);  
    Cake c2 = new Cake(2);  
    Cake c3 = new Cake(3);  

    c2 = c3 = null;  
    System.gc(); //调用Java垃圾收集器
  }  
}  

class Cake extends Object {  
  private int id;  
  public Cake(int id) {  
    this.id = id;  
    System.out.println("Cake Object " + id + "is created");  
  }  

  protected void finalize() throws java.lang.Throwable {  
    super.finalize();  
    System.out.println("Cake Object " + id + "is disposed");  
  }  
}
运行以上代码,输出结果如下:

$ javac FinalizationDemo.java 
$ java FinalizationDemo
Cake Object 1is created
Cake Object 2is created
Cake Object 3is created
Cake Object 3is disposed
Cake Object 2is disposed
LastPoem commented 4 years ago

Java 流(Stream)、文件(File)和IO

Java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。 Java.io 包中的流支持很多种格式,比如:基本类型、对象、本地化字符集等等。 一个流可以理解为一个数据的序列。输入流表示从一个源读取数据,输出流表示向一个目标写数据。 Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。 但本节讲述最基本的和流与 I/O 相关的功能。我们将通过一个个例子来学习这些功能。

读取控制台输入 Java 的控制台输入由 System.in 完成。 为了获得一个绑定到控制台的字符流,你可以把 System.in 包装在一个 BufferedReader 对象中来创建一个字符流。 下面是创建 BufferedReader 的基本语法:

BufferedReader br = new BufferedReader(new 
                      InputStreamReader(System.in));

BufferedReader 对象创建后,我们便可以使用 read() 方法从控制台读取一个字符,或者用 readLine() 方法读取一个字符串。

从控制台读取多字符输入

import java.io.*;

public class BRRead {
    public static void main(String args[]) throws IOException {
        char c;
        // 使用 System.in 创建 BufferedReader
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("输入字符, 按下 'q' 键退出。");
        // 读取字符
        do {
            c = (char) br.read();
            System.out.println(c);
        } while (c != 'q');
    }
}

从控制台读取字符串 从标准输入读取一个字符串需要使用 BufferedReader 的 readLine() 方法。 它的一般格式是: String readLine( ) throws IOException

控制台输出 在此前已经介绍过,控制台的输出由 print( ) 和 println() 完成。这些方法都由类 PrintStream 定义,System.out 是该类对象的一个引用。 PrintStream 继承了 OutputStream类,并且实现了方法 write()。这样,write() 也可以用来往控制台写操作。 PrintStream 定义 write() 的最简单格式如下所示: void write(int byteval)

读写文件

iostream2xx

FileInputStream 该流用于从文件读取数据,它的对象可以用关键字 new 来创建。 有多种构造方法可用来创建对象。 可以使用字符串类型的文件名来创建一个输入流对象来读取文件: InputStream f = new FileInputStream("C:/java/hello");

也可以使用一个文件对象来创建一个输入流对象来读取文件。我们首先得使用 File() 方法来创建一个文件对象: File f = new File("C:/java/hello"); InputStream out = new FileInputStream(f);

序号 方法及描述
1 public void close() throws IOException{}关闭此文件输入流并释放与此流有关的所有系统资源。抛出IOException异常。
2 protected void finalize()throws IOException {}这个方法清除与该文件的连接。确保在不再引用文件输入流时调用其 close 方法。抛出IOException异常。
3 public int read(int r)throws IOException{}这个方法从 InputStream 对象读取指定字节的数据。返回为整数值。返回下一字节数据,如果已经到结尾则返回-1。
4 public int read(byte[] r) throws IOException{}这个方法从输入流读取r.length长度的字节。返回读取的字节数。如果是文件结尾则返回-1。
5 public int available() throws IOException{}返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取的字节数。返回一个整数值。

FileOutputStream 该类用来创建一个文件并向文件中写数据。 如果该流在打开文件进行输出前,目标文件不存在,那么该流会创建该文件。 有两个构造方法可以用来创建 FileOutputStream 对象。

使用字符串类型的文件名来创建一个输出流对象: OutputStream f = new FileOutputStream("C:/java/hello")

也可以使用一个文件对象来创建一个输出流来写文件。我们首先得使用File()方法来创建一个文件对象: File f = new File("C:/java/hello"); OutputStream f = new FileOutputStream(f);

序号 方法及描述
1 public void close() throws IOException{}关闭此文件输入流并释放与此流有关的所有系统资源。抛出IOException异常。
2 protected void finalize()throws IOException {}这个方法清除与该文件的连接。确保在不再引用文件输入流时调用其 close 方法。抛出IOException异常。
3 public void write(int w)throws IOException{}这个方法把指定的字节写到输出流中。
4 public void write(byte[] w)把指定数组中w.length长度的字节写到OutputStream中。
//文件名 :fileStreamTest2.java
import java.io.*;

public class fileStreamTest2 {
    public static void main(String[] args) throws IOException {

        File f = new File("a.txt");
        FileOutputStream fop = new FileOutputStream(f);
        // 构建FileOutputStream对象,文件不存在会自动新建

        OutputStreamWriter writer = new OutputStreamWriter(fop, "UTF-8");
        // 构建OutputStreamWriter对象,参数可以指定编码,默认为操作系统默认编码,windows上是gbk

        writer.append("中文输入");
        // 写入到缓冲区

        writer.append("\r\n");
        // 换行

        writer.append("English");
        // 刷新缓存冲,写入到文件,如果下面已经没有写入的内容了,直接close也会写入

        writer.close();
        // 关闭写入流,同时会把缓冲区内容写入文件,所以上面的注释掉

        fop.close();
        // 关闭输出流,释放系统资源

        FileInputStream fip = new FileInputStream(f);
        // 构建FileInputStream对象

        InputStreamReader reader = new InputStreamReader(fip, "UTF-8");
        // 构建InputStreamReader对象,编码与写入相同

        StringBuffer sb = new StringBuffer();
        while (reader.ready()) {
            sb.append((char) reader.read());
            // 转成char加到StringBuffer对象中
        }
        System.out.println(sb.toString());
        reader.close();
        // 关闭读取流

        fip.close();
        // 关闭输入流,释放系统资源

    }
}

Java中的目录

创建目录 File类中有两个方法可以用来创建文件夹:

mkdir( )方法创建一个文件夹,成功则返回true,失败则返回false。失败表明File对象指定的路径已经存在,或者由于整个路径还不存在,该文件夹不能被创建。

mkdirs()方法创建一个文件夹和它的所有父文件夹。 下面的例子创建 "/tmp/user/java/bin"文件夹:

import java.io.File;

public class CreateDir {
    public static void main(String args[]) {
        String dirname = "/tmp/user/java/bin";
        File d = new File(dirname);
        // 现在创建目录
        d.mkdirs();
    }
}

编译并执行上面代码来创建目录 "/tmp/user/java/bin"。

读取目录 一个目录其实就是一个 File 对象,它包含其他文件和文件夹。 如果创建一个 File 对象并且它是一个目录,那么调用 isDirectory() 方法会返回 true。 可以通过调用该对象上的 list() 方法,来提取它包含的文件和文件夹的列表。 下面展示的例子说明如何使用 list() 方法来检查一个文件夹中包含的内容:

import java.io.File;

public class DirList {
    public static void main(String args[]) {
        String dirname = "/tmp";
        File f1 = new File(dirname);
        if (f1.isDirectory()) {
            System.out.println("目录 " + dirname);
            String s[] = f1.list();
            for (int i = 0; i < s.length; i++) {
                File f = new File(dirname + "/" + s[i]);
                if (f.isDirectory()) {
                    System.out.println(s[i] + " 是一个目录");
                } else {
                    System.out.println(s[i] + " 是一个文件");
                }
            }
        } else {
            System.out.println(dirname + " 不是一个目录");
        }
    }
}

以上实例编译运行结果如下:

目录 /tmp bin 是一个目录 lib 是一个目录 demo 是一个目录 test.txt 是一个文件 README 是一个文件 index.html 是一个文件 include 是一个目录

删除目录或文件 删除文件可以使用 java.io.File.delete() 方法。

以下代码会删除目录 /tmp/java/,需要注意的是当删除某一目录时,必须保证该目录下没有其他文件才能正确删除,否则将删除失败。

测试目录结构:

/tmp/java/ |-- 1.log |-- test

import java.io.File;

public class DeleteFileDemo {
    public static void main(String args[]) {
        // 这里修改为自己的测试目录
        File folder = new File("/tmp/java/");
        deleteFolder(folder);
    }

    // 删除文件及目录
    public static void deleteFolder(File folder) {
        File[] files = folder.listFiles();
        if (files != null) {
            for (File f : files) {
                if (f.isDirectory()) {
                    deleteFolder(f);
                } else {
                    f.delete();
                }
            }
        }
        folder.delete();
    }
}
LastPoem commented 4 years ago

Java Scanner类 可以通过 Scanner 类来获取用户的输入。 下面是创建 Scanner 对象的基本语法: Scanner s = new Scanner(System.in);

使用 next 方法:

import java.util.Scanner; 

public class ScannerDemo {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        // 从键盘接收数据

        // next方式接收字符串
        System.out.println("next方式接收:");
        // 判断是否还有输入
        if (scan.hasNext()) {
            String str1 = scan.next();
            System.out.println("输入的数据为:" + str1);
        }
        scan.close();
    }
}

next方式接收: runoob com 输入的数据为:runoob

使用 nextLine 方法:

import java.util.Scanner;
public class ScannerDemo {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        // 从键盘接收数据

        // nextLine方式接收字符串
        System.out.println("nextLine方式接收:");
        // 判断是否还有输入
        if (scan.hasNextLine()) {
            String str2 = scan.nextLine();
            System.out.println("输入的数据为:" + str2);
        }
        scan.close();
    }
}

nextLine方式接收: runoob com 输入的数据为:runoob com

next() 与 nextLine() 区别 next(): 1、一定要读取到有效字符后才可以结束输入。 2、对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。 3、只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。 next() 不能得到带有空格的字符串。

nextLine(): 1、以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。 2、可以获得空白。

LastPoem commented 4 years ago

Java异常处理

异常发生的原因有很多,通常包含以下几大类:

需要掌握以下三种类型的异常:

  1. 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在的文件时,异常就发生了,这些异常在编译时不能被简单的忽略
  2. 运行时异常:运行时异常是可能被程序员避免的异常,与检查性异常相反,运行时异常可以在编译时被忽略。
  3. 错误:错误不是异常,是脱离程序员控制的问题,错误在代码中通常被忽略,例如当栈溢出时,一个错误就发生了。这在编译时是检查不到的。

Exception 类的层次

所有的异常类是从 java.lang.Exception 类继承的子类。 Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。 Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。 Error 用来指示运行时环境发生的错误。 例如,JVM 内存溢出。一般地,程序不会从错误中恢复。 异常类有两个主要的子类:IOException 类和 RuntimeException 类。

Java内置异常类 Java 语言定义了一些异常类在 java.lang 标准包中。 标准运行时异常类的子类是最常见的异常类。由于 java.lang 包是默认加载到所有的 Java 程序的,所以大部分从运行时异常类继承而来的异常都可以直接使用。 Java 根据各个类库也定义了一些其他的异常,下面的表中列出了 Java 的非检查性异常。

异常 描述
ArithmeticException 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。
ArrayIndexOutOfBoundsException 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。
ArrayStoreException 试图将错误类型的对象存储到一个对象数组时抛出的异常。
ClassCastException 当试图将对象强制转换为不是实例的子类时,抛出该异常。
IllegalArgumentException 抛出的异常表明向方法传递了一个不合法或不正确的参数。
IllegalMonitorStateException 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。
IllegalStateException 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。
IllegalThreadStateException 线程没有处于请求操作所要求的适当状态时抛出的异常。
IndexOutOfBoundsException 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。
NegativeArraySizeException 如果应用程序试图创建大小为负的数组,则抛出该异常。
NullPointerException 当应用程序试图在需要对象的地方使用 null 时,抛出该异常
NumberFormatException 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。
SecurityException 由安全管理器抛出的异常,指示存在安全侵犯。
StringIndexOutOfBoundsException 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。
UnsupportedOperationException 当不支持请求的操作时,抛出该异常。
异常 描述
ClassNotFoundException 应用程序试图加载类时,找不到相应的类,抛出该异常。
CloneNotSupportedException 当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。
IllegalAccessException 拒绝访问一个类的时候,抛出该异常。
InstantiationException 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。
InterruptedException 一个线程被另一个线程中断,抛出该异常。
NoSuchFieldException 请求的变量不存在
NoSuchMethodException 请求的方法不存在

异常方法

序号 方法及说明
1 public String getMessage()返回关于发生的异常的详细信息。这个消息在Throwable 类的构造函数中初始化了。
2 public Throwable getCause()返回一个Throwable 对象代表异常原因。
3 public String toString()使用getMessage()的结果返回类的串级名字。
4 public void printStackTrace()打印toString()结果和栈层次到System.err,即错误输出流。
5 public StackTraceElement [] getStackTrace()返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。
6 public Throwable fillInStackTrace()用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。

捕获异常 使用try catch 关键字可以捕获异常。try/catch代码块放在异常可能发生地地方。 try/catch代码块中的代码称为保护代码,使用 try/catch 的语法如下:

try
{
   // 程序代码
}catch(ExceptionName e1)
{
   //Catch 块
}

Catch 语句包含要捕获异常类型的声明。当保护代码块中发生一个异常时,try 后面的 catch 块就会被检查。 如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块,这和传递一个参数到方法是一样。

实例:

import java.io.*;
public class ExcepTest{

   public static void main(String args[]){
      try{
         int a[] = new int[2];
         System.out.println("Access element three :" + a[3]);
      }catch(ArrayIndexOutOfBoundsException e){
         System.out.println("Exception thrown  :" + e);
      }
      System.out.println("Out of the block");
   }
}

以上代码声明有两个元素的一个数组,当试图访问数组第三个元素时就会抛出一个异常。 运行结果 Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3 Out of the block

多重捕获块 一个try代码块后面跟随多个catch代码块的情况就叫多重捕获

try{
   // 程序代码
}catch(异常类型1 异常的变量名1){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}

多重捕获块的实例:

try {
    file = new FileInputStream(fileName);
    x = (byte) file.read();
} catch(FileNotFoundException f) { // Not valid!
    f.printStackTrace();
    return -1;
} catch(IOException i) {
    i.printStackTrace();
    return -1;
}

throws/throw 关键字: 如果一个方法没有捕获到一个检查性异常,该方法必须使用throws关键字来声明。throws关键字放在方法签名的尾部。也可以用throw关键字来抛出一个异常,无论它是新实例化的还是刚捕获的。

下面方法的声明抛出一个 RemoteException 异常:

import java.io.*;
public class className
{
  public void deposit(double amount) throws RemoteException
  {
    // Method implementation
    throw new RemoteException();
  }
  //Remainder of class definition
}

一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。 例如,下面的方法声明抛出 RemoteException 和 InsufficientFundsException:

import java.io.*;
public class className
{
   public void withdraw(double amount) throws RemoteException,
                              InsufficientFundsException
   {
       // Method implementation
   }
   //Remainder of class definition
}

finally关键字

finally 关键字用来创建在 try 代码块后面执行的代码块。 无论是否发生异常,finally 代码块中的代码总会被执行。 在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。 finally 代码块出现在 catch 代码块最后,语法如下:

try{
  // 程序代码
}catch(异常类型1 异常的变量名1){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}finally{
  // 程序代码
}

实例

public class ExcepTest{
  public static void main(String args[]){
    int a[] = new int[2];
    try{
       System.out.println("Access element three :" + a[3]);
    }catch(ArrayIndexOutOfBoundsException e){
       System.out.println("Exception thrown  :" + e);
    }
    finally{
       a[0] = 6;
       System.out.println("First element value: " +a[0]);
       System.out.println("The finally statement is executed");
    }
  }
}

以上实例编译运行结果如下:

Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: 3
First element value: 6
The finally statement is executed

声明自定义异常

  1. 所有异常都必须是 Throwable 的子类。
  2. 如果希望写一个检查性异常类,则需要继承 Exception 类。
  3. 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。