Java教程 第6页 重写 (Override) 重写是子类对父类的允许访问的方法的实现过程进行重新编写!返回值和形参都不能改变。即外壳不变,核心重写! 重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。 在面向对象原则里,重写意味着可以重写任何现有方法。实例如下: class Animal{ public void move(){ System.out.println("动物可以移动"); } } class Dog extends Animal{ public void move(){ System.out.println("狗可以跑和走"); } } public class TestDog{ public static void main(String args[]){ Animal a = new Animal(); // Animal 对象 Animal b = new Dog(); // Dog 对象 a.move();// 执行 Animal 类的方法 b.move();//执行 Dog 类的方法 } } 以上实例编译运行结果如下: 动物可以移动 狗可以跑和走 在上面的例子中可以看到,尽管 b 属于 Animal 类型,但是它运行的是 Dog 类的 move 方法。 这是由于在编译阶段,只是检查参数的引用类型。 然而在运行时,Java 虚拟机 (JVM) 指定对象的类型并且运行该对象的方法。 因此在上面的例子中,之所以能编译成功,是因为 Animal 类中存在 move 方法,然而运行时,运行的是特定对象的方法。 思考以下例子: class Animal{ public void move(){ System.out.println("动物可以移动"); } } class Dog extends Animal{ public void move(){ System.out.println("狗可以跑和走"); } public void bark(){ System.out.println("狗可以吠叫"); } } public class TestDog{ public static void main(String args[]){ Animal a = new Animal(); // Animal 对象 Animal...
2024-04-01
什么是异常? 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常。异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?或者用C语言风格:用函数返回值作为执行状态?在Java中,异常就是Java在编译或运行或者运行过程中出现的错误。 异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。 比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error;如果你用 System.out.println(11/0),那么你是因为你用 0 做了除数,会抛出 java.lang.ArithmeticException 的异常。 异常发生的原因有很多,通常包含以下几大类: 用户输入了非法数据。 要打开的文件不存在。 网络通信时连接中断,或者 JVM 内存溢出。 这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。- 要理解 Java 异常处理是如何工作的,你需要掌握以下三种类型的异常: 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。 Exception 类的层次 所有的异常类是从 java.lang.Exception 类继承的子类。 Exception 类是 Throwable 类的子类。除了Exception类外,Throwable 还有一个子类 Error 。 Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在 Java 程序处理的范畴之外。 Error 用来指示运行时环境发生的错误。 例如,JVM 内存溢出。一般地,程序不会从错误中恢复。 异常类有两个主要的子类:IOException 类和 RuntimeException 类。 在 Java 内置类中(接下来会说明),有大部分常用检查性和非检查性异常。 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 当不支持请求的操作时,抛出该异常。 下面的表中列出了 Java 定义在 java.lang 包中的检查性异常类。 异常 描述 ClassNotFoundException 应用程序试图加载类时,找不到相应的类,抛出该异常。 CloneNotSupportedException 当调用 Object 类中的...
2024-04-01
java.util.Scanner是Java5的新特征,我们可以通过 Scanner 类来获取用户的输入。 下面是创建 Scanner 对象的基本语法: Scanner s = new Scanner(System.in); 接下来我们演示一个最简单的的数据输入,并通过 Scanner 类的 next() 与 nextLine() 方法获取输入的字符串,在读取前我们一般需要 使用 hasNext 与 hasNextLine 判断是否还有输入的数据: 使用 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); } } } 执行以上程序输出结果为: $ javac ScannerDemo.java $ java ScannerDemo next方式接收: youj com 输入的数据为:youj 可以看到 com 字符串并未输出,接下来我们看 nextLine。 使用 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); } } } 执行以上程序输出结果为: $ javac ScannerDemo.java $ java ScannerDemo nextLine方式接收: youj com 输入的数据为:youj com...
2024-04-01
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() 方法读取一个字符串。 从控制台读取多字符输入 从 BufferedReader 对象读取一个字符要使用 read() 方法,它的语法如下: int read() throws IOException 每次调用 read() 方法,它从输入流读取一个字符并把该字符作为整数值返回。 当流结束的时候返回 -1。该方法抛出 IOException。 下面的程序示范了用 read() 方法从控制台不断读取字符直到用户输入 “q” 。 // 使用 BufferedReader 在控制台读取字符 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'); } } 以上实例编译运行结果如下: 输入字符, 按下 'q' 键退出. 123abcq 1 2 3 a b c q 从控制台读取字符串 从标准输入读取一个字符串需要使用 BufferedReader 的 readLine() 方法。 它的一般格式是: String readLine() throws IOException 下面的程序读取和显示字符行直到你输入了单词 “end”。 // 使用 BufferedReader 在控制台读取字符 import java.io.*; public class BRReadLines { public static void main(String args[]) throws IOException { // 使用 System.in 创建 BufferedReader BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str; System.out.println("Enter lines of text."); System.out.println("Enter 'end' to quit."); do { str = br.readLine(); System.out.println(str); } while(!str.equals("end")); } } 以上实例编译运行结果如下: Enter lines of text. Enter 'end' to quit. This is line one This is line one This is line two This is line two end end 控制台输出 在此前已经介绍过,控制台的输出由...
2024-04-01
在前面几个章节中我们经常使用到System.out.println(),那么它是什么呢? println()是一个方法(Method),而System是系统类(Class),out是标准输出对象(Object)。这句话的用法是调用系统类System中的标准输出对象out中的方法println()。 那么什么是方法呢? Java方法是语句的集合,它们在一起执行一个功能。 方法是解决一类问题的步骤的有序组合 方法包含于类或对象中 方法在程序中被创建,在其他地方被引用 方法的定义 一般情况下,定义一个方法包含以下语法: 修饰符 返回值类型 方法名 (参数类型 参数名){ ... 方法体 ... return 返回值; } 方法包含一个方法头和一个方法体。下面是一个方法的所有部分: 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。 返回值类型 :方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字void。 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。 方法体:方法体包含具体的语句,定义该方法的功能。 如: public static int age(int birthday){...} 参数可以有多个: static float interest(float principal, int year){...} 注意: 在一些其它语言中方法指过程和函数。一个返回非void类型返回值的方法称为函数;一个返回void类型返回值的方法叫做过程。 实例 下面的方法包含2个参数num1和num2,它返回这两个参数的最大值。 /** 返回两个整型变量数据的较大值 */ public static int max(int num1, int num2) { int result; if (num1 > num2){ result = num1; }else{ result = num2; } return result; } 方法调用 Java支持两种调用方法的方式,根据方法是否返回值来选择。 当程序调用一个方法时,程序的控制权交给了被调用的方法。当被调用方法的返回语句执行或者到达方法体闭括号时候交还控制权给程序。 当方法返回一个值的时候,方法调用通常被当做一个值。例如: int larger = max(30, 40); 如果方法返回值是void,方法调用一定是一条语句。例如,方法println返回void。下面的调用是个语句: System.out.println("Welcome to Java!"); 示例 下面的例子演示了如何定义一个方法,以及如何调用它: public class TestMax { /** 主方法 */ public static void main(String[] args) { int i = 5; int j = 2; int k = max(i, j); System.out.println("The maximum between " + i + " and " + j + " is " + k); } /** 返回两个整数变量较大的值 */ public static int max(int num1, int num2) { int result; if (num1 > num2){ result = num1; }else{ result = num2; } return result; } } 以上实例编译运行结果如下: The maximum between 5 and 2 is 5 这个程序包含main方法和max方法。Main方法是被JVM调用的,除此之外,main方法和其它方法没什么区别。 main方法的头部是不变的,如例子所示,带修饰符public和static,返回void类型值,方法名字是main,此外带个一个String[]类型参数。String[]表明参数是字符串数组。 void 关键字 本节说明如何声明和调用一个void方法。 下面的例子声明了一个名为printGrade的方法,并且调用它来打印给定的分数。 示例 public class TestVoidMethod { public static void main(String[] args) { printGrade(78.5); } public static void printGrade(double score) { if (score >= 90.0) { System.out.println('A'); } else if (score >= 80.0) { System.out.println('B'); } else if (score >= 70.0) { System.out.println('C'); } else if (score >= 60.0) { System.out.println('D'); } else { System.out.println('F'); } } } 以上实例编译运行结果如下: C 这里printGrade方法是一个void类型方法,它不返回值。 一个void方法的调用一定是一个语句。 所以,它被在main方法第三行以语句形式调用。就像任何以分号结束的语句一样。 通过值传递参数 调用一个方法时候需要提供参数,你必须按照参数列表指定的顺序提供。 例如,下面的方法连续n次打印一个消息: public static void nPrintln(String message, int n) { for (int i = 0; i < n; i++) System.out.println(message); } 示例 下面的例子演示按值传递的效果。 该程序创建一个方法,该方法用于交换两个变量。 public class TestPassByValue { public static void main(String[] args) { int num1 = 1;...
2024-04-01
正则表达式定义了字符串的模式。 正则表达式可以用来搜索、编辑或处理文本。 正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。 Java正则表达式和Perl的是最为相似的。 java.util.regex包主要包括以下三个类: Pattern类: pattern对象是一个正则表达式的编译表示。Pattern类没有公共构造方法。要创建一个Pattern对象,你必须首先调用其公共静态编译方法,它返回一个Pattern对象。该方法接受一个正则表达式作为它的第一个参数。 Matcher类: Matcher对象是对输入字符串进行解释和匹配操作的引擎。与Pattern类一样,Matcher也没有公共构造方法。你需要调用Pattern对象的matcher方法来获得一个Matcher对象。 PatternSyntaxException: PatternSyntaxException是一个非强制异常类,它表示一个正则表达式模式中的语法错误。 捕获组 捕获组是把多个字符当一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。 例如,正则表达式(dog) 创建了单一分组,组里包含”d”,”o”,和”g”。 捕获组是通过从左至右计算其开括号来编号。例如,在表达式((A)(B(C))),有四个这样的组: ((A)(B(C))) (A) (B(C)) (C) 可以通过调用matcher对象的groupCount方法来查看表达式有多少个分组。groupCount方法返回一个int值,表示matcher对象当前有多个捕获组。 还有一个特殊的组(组0),它总是代表整个表达式。该组不包括在groupCount的返回值中。 实例 下面的例子说明如何从一个给定的字符串中找到数字串: import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexMatches { public static void main( String args[] ){ // 按指定模式在字符串查找 String line = "This order was placed for QT3000! OK?"; String pattern = "(.*)(\\d+)(.*)"; // 创建 Pattern 对象 Pattern r = Pattern.compile(pattern); // 现在创建 matcher 对象 Matcher m = r.matcher(line); if (m.find( )) { System.out.println("Found value: " + m.group(0) ); System.out.println("Found value: " + m.group(1) ); System.out.println("Found value: " + m.group(2) ); } else { System.out.println("NO MATCH"); } } } 以上实例编译运行结果如下: Found value: This order was placed for QT3000! OK? Found value: This order was placed for QT300 Found...
2024-04-01
数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同。 Java 语言中提供的数组是用来存储固定大小的同类型元素。 你可以声明一个数组变量,如 numbers[100] 来代替直接声明 100 个独立变量 number0,number1,….,number99。 本教程将为大家介绍Java数组的声明、创建和初始化,并给出其对应的代码。 声明数组变量 首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法: dataType[] arrayRefVar; // 首选的方法 或 dataType arrayRefVar[]; // 效果相同,但不是首选方法 注意: 建议使用 dataType[] arrayRefVar 的声明风格声明数组变量。 dataType arrayRefVar[] 风格是来自 C/C++ 语言 ,在Java中采用是为了让 C/C++ 程序员能够快速理解 java 语言。 实例 下面是这两种语法的代码示例: double[] myList; // 首选的方法 或 double myList[]; // 效果相同,但不是首选方法 创建数组 Java 语言使用 new操作符来创建数组,语法如下: arrayRefVar = new dataType[arraySize]; 上面的语法语句做了两件事: 一、使用 dataType[arraySize] 创建了一个数组。 二、把新创建的数组的引用赋值给变量 arrayRefVar。 数组变量的声明,和创建数组可以用一条语句完成,如下所示: dataType[] arrayRefVar = new dataType[arraySize]; 另外,你还可以使用如下的方式创建数组。 dataType[] arrayRefVar = {value0, value1, ..., valuek}; 数组的元素是通过索引访问的。数组索引从0开始,所以索引值从 0 到 arrayRefVar.length-1。 那么当数组开辟空间之后,就可以采用如下的方式的操作: 数组的访问通过索引完成,即:“数组名称[索引]”,但是需要注意的是,数组的索引从0开始,所以索引的范围就是0 ~ 数组长度-1,例如开辟了3个空间的数组,所以可以使用的索引是:0,1,2,如果此时访问的时候超过了数组的索引范围,会产生 java.lang.ArrayIndexOutOfBoundsException 异常信息; 当我们数组采用动态初始化开辟空间后,数组里面的每一个元素都是该数组对应数据类型的默认值; 数组本身是一个有序的集合操作,所以对于数组的内容操作往往会采用循环的模式完成,数组是一个有限的数据集合,所以应该使用 for 循环。 在 Java 中提供有一种动态取得数组长度的方式:数组名称.length; 示例: 定义一个int型数组 public class ArrayDemo { public static void main(String args[]) { int data[] = new int[3]; /*开辟了一个长度为3的数组*/ data[0] = 10; // 第一个元素 data[1] = 20; // 第二个元素 data[2] = 30; // 第三个元素 for(int x = 0; x < data.length; x++) { System.out.println(data[x]); //通过循环控制索引 } } } 数组本身除了声明并开辟空间之外还有另外一种开辟模式。 示例: 采用分步的模式开辟数组空间 public class ArrayDemo { public static void main(String args[]) {...
2024-04-01
当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。 和String类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。 StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据)。 由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。 实例 public class Test{ public static void main(String args[]){ StringBuffer sBuffer = new StringBuffer(" test"); sBuffer.append(" String Buffer"); System.out.println(sBuffer); } } 以上实例编译运行结果如下: test String Buffer StringBuffer 方法 以下是 StringBuffer 类支持的主要方法: 序号 方法描述 1 public StringBuffer append(String s) 将指定的字符串追加到此字符序列。 2 public StringBuffer reverse() 将此字符序列用其反转形式取代。 3 public delete(int start, int end) 移除此序列的子字符串中的字符。 4 public insert(int offset, int i) 将 int 参数的字符串表示形式插入此序列中。 5 replace(int start, int end, String str) 使用给定 String 中的字符替换此序列的子字符串中的字符。 下面的列表里的方法和 String 类的方法类似: 序号 方法描述 1 int capacity() 返回当前容量。 2 char charAt(int index) 返回此序列中指定索引处的 char 值。 3 void ensureCapacity(int minimumCapacity) 确保容量至少等于指定的最小值。 4 void getChars(int...
2024-04-01
字符串广泛应用在Java编程中,在Java中字符串属于对象,Java提供了String类来创建和操作字符串。 创建字符串 创建字符串最简单的方式如下: String greeting = "Hello world!"; 在代码中遇到字符串常量时,这里的值是 “Hello world!” ,编译器会使用该值创建一个 String 对象。 和其它对象一样,可以使用关键字和构造方法来创建String对象。 String 类有 11 种构造方法,这些方法提供不同的参数来初始化字符串,比如提供一个字符数组参数: public class StringDemo{ public static void main(String args[]){ char[] helloArray = { 'h', 'e', 'l', 'l', 'o', '.'}; String helloString = new String(helloArray); System.out.println( helloString ); } } 以上实例编译运行结果如下: hello. 注意:String 类是不可改变的,所以你一旦创建了 String 对象,那它的值就无法改变了。 如果需要对字符串做很多修改,那么应该选择使用 StringBuffer & StringBuilder 类。 字符串长度 用于获取有关对象的信息的方法称为访问器方法。 String 类的一个访问器方法是 length() 方法,它返回字符串对象包含的字符数。 下面的代码执行后,len 变量等于 17: public class StringDemo { public static void main(String args[]) { String palindrome = "Dot saw I was Tod"; int len = palindrome.length(); System.out.println( "String Length is : " + len ); } } 以上实例编译运行结果如下: String Length is : 17 连接字符串 String 类提供了连接两个字符串的方法: string1.concat(string2); 返回 string2 连接 string1 的新字符串。也可以对字符串常量使用 concat() 方法,如: "My name is ".concat("Zara");...
2024-04-01
本章节我们主要向大家介绍一下Java Character类,以及Character类的用法。 Java Character类 使用字符时,我们通常使用的是内置数据类型 char。 实例 char ch = 'a'; // Unicode for uppercase Greek omega character char uniChar = '\u039A'; // 字符数组 char[] charArray = { 'a', 'b', 'c', 'd', 'e' }; 然而,在实际开发过程中,我们经常会遇到需要使用对象,而不是内置数据类型的情况。为了解决这个问题,Java 语言为内置数据类型 char 提供了包装类 Character 类。 Character类的用法:Character 类提供了一系列方法来操纵字符,你可以使用 Character 的构造方法创建一个 Character 类对象,例如: Character ch = new Character('a'); 在某些情况下,Java 编译器会自动创建一个 Character 对象。 例如,将一个 char 类型的参数传递给需要一个 Character 类型参数时,那么编译器会自动地将 char 类型参数转换为 Character 对象。 这种特征称为装箱,反过来称为拆箱。 实例 // Here following primitive char 'a' // is boxed into the Character object ch Character ch = 'a'; // Here primitive 'x' is boxed for method test, // return is unboxed to char 'c' char c = test('x'); 转义序列 前面有反斜杠(\)的字符代表转义字符,它对编译器来说是有特殊含义的。 下面列表展示了 Java 的转义序列: 转义序列 描述 \t 在文中该处插入一个tab键 \b 在文中该处插入一个后退键 \n 在文中该处换行 \r 在文中该处插入回车 \f...
2024-04-01