【Java学习系列】第2课--Java语法及面向对象
分享提纲:
2.6 Java StringBuffer 和 StringBuilder 类
2.11 Java 流(Stream)、文件(File)和IO
2.13 Java 重写(Override)与重载(Overload)
本文主要介绍下Java程序的特点(不同于PHP的地方)和面向对象的一些特点
1. Java程序特点
【示例代码】
public class HelloWorld {
/* 第一个Java程序
* 它将打印字符串 Hello World
*/
public static void main(String []args) {
System.out.println("Hello World"); // 打印 Hello World
}
}
执行过程如下(图像演示):
C : > javac HelloWorld.java
C : > java HelloWorld
Hello World
1)【基本语法】
a)【大小写敏感】
Java的类和函数是大小写敏感的,这一点和PHP不同,PHP的类和函数的大小写不敏感
b)【源文件名】
--【一个文件只能有一个类】源文件名必须和类名相同。当保存文件的时候,你应该使用类名作为文件名保存(切记Java是大小写敏感的),文件名的后缀为.java。(如果文件名和类名不相同则会导致编译错误)。
-- PHP没有这样的要求,因为PHP本身就是解释型的语言,不需要编译,也不需要生成编译文件类似 .class的文件
c)【主方法入口】
--必须有main方法(静态方法):所有的Java 程序由public static void main(String []args)方法开始执行。
--【也有例外】
java很多知识的,如果是单纯的javaApplication(java应用程序)应该有main()函数作为入口,但是像jsp或者是applet等都是不需要main()函数的
d)【每个变量都要先定义,并制定类型】
-- 这也是与PHP语言的不同点
2)【字符串】
a)【必须用双引号引着】
b) 【连接符】java中的字符串的链接符号是 "+", 不像PHP中是 ".",因为 "." 在Java中是 类中的变量的链接符。
3)【变量】
a)变量必须执行类型,且先定义
b)【种类】
--【概述】
Java有两大数据类型,内置数据类型 和 引用数据类型
内置数据类型:
Java语言提供了八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。 byte, short, int, long, float, double, boolean, char
引用数据类型:
--在Java中,引用类型的变量非常类似于C/C++的指针。引用类型指向一个对象,指向对象的变量是引用变量。这些变量在声明时被指定为一个特定的类型,比如Employee、Pubby等。变量一旦声明后,类型就不能被改变了。
-- 对象、数组都是引用数据类型。
--所有引用类型的默认值都是null。
-- 一个引用变量可以用来引用与任何与之兼容的类型。
-- 例子:Site site = new Site("Runoob")。
c)【常量】
-- 在 Java 中使用 final 关键字来修饰常量,声明方式和变量类似
4)【Java数组】
a)数组是储存在堆上的对象,可以保存多个同类型变量。
5)【Java枚举】
a)Java 5.0引入了枚举,枚举限制变量只能是预先设定好的值。使用枚举可以减少代码中的bug。
b)【语法】
class FreshJuice {
enum FreshJuiceSize{ SMALL, MEDUIM, LARGE }
FreshJuiceSize size;
}
6)【Java修饰符】
-- 访问修饰符 分类如下
a) 默认的,也称为 default,在同一包内可见,不使用任何修饰符。 b) 私有的,以 private 修饰符指定,在同一类内可见。 c) 共有的,以 public 修饰符指定,对所有类可见。 d) 受保护的,以 protected 修饰符指定,对同一包内的类和所有子类可见。
-- 非访问修饰符:
a)【Synchronized 修饰符】:
-- Synchronized 关键字声明的方法同一时间只能被一个线程访问。Synchronized 修饰符可以应用于四个访问修饰符。
--
public synchronized void showDetails(){
.......
} b)【Transient 修饰符】:
--序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。 --该修饰符包含在定义变量的语句中,用来预处理类和变量的数据类型。 -- 实例
public transient int limit = 55; // 不会持久化
public int b; // 持久化 c) 【Volatile修饰符】
--volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。 -- 一个 volatile 对象引用可能是 null。
7)【Java编译制定在制定目录】
2. Java面向对象
【代码示例】
该文件名为 TestJavaClass.java ,对应文件里唯一的一个 public的类的类名。
实现的功能就是 示例化一个 狗的对象,同时设置狗的年龄并得到该年龄,然后输出.
javac TestJavaClass.java
java TestJavaClass
//1. 入口测试类
public class TestJavaClass
{//{{{
public static void main(String []args)
{//{{{
//注意点1:实例化要制定类型 TestDog
//注意点2:java程序中的字符串必须是 双引号引着
TestDog testDog = new TestDog("Tom");
testDog.run();
}//}}} }//}}} //2.测试小狗类
class TestDog
{//{{{
String name;
int age;
//构造函数
public TestDog (String name)
{//{{{
System.out.println("这条狗叫 " + name);
}//}}} //运行
public void run()
{//{{{
System.out.println("01 开始运行\n");
//注意点3:类的内部调动函数,直接写 setAge(dogAge)
setAge(10);
int dogAge = getAge();
System.out.println("02 狗的年龄是 " + dogAge);
}//}}} //获取
public int getAge()
{//{{{
return age;
}//}}} //设置
public void setAge(int ageValue)
{//{{{
//注意点4:类的内部调动类的成员变量,直接写 age
age = ageValue;
}//}}} }//}}}
1)【Java的类和对象】
a)【调用函数和变量】
类内部调用函数,直接就是 函数名本身,直接写 setAge(dogAge),变量也是直接写 age
b)【类的修饰】
PHP中类的修饰,最多就是 抽象类为 abstract class ,但是在 Java中一个文件中必须有一个 public class,且为该文件的名。
c)【定义类的函数】
-- PHP中常见的是 public function functionName()
-- 在Java中,则不需要 fuction的说明,但是要执行返回值类型, public void functionName()
d)【构造方法】
--PHP中的构造方法是 public function __construct(){} ,且只能有一个
--Java的构造方法可以有多个,在创建一个对象的时候,至少要调用一个构造方法。构造方法的名称必须与类同名,一个类可以有多个构造方法,从而实现不同情况下走不同的构造方法。
例如:
public class A{
public A(){
System.out.println("调用了A的无参构造函数");
}
public A(String mess){
System.out.println("调用了A的有参的构造函数\n"+
"参数内容为:"+mess);
}
}
2)【类的一些注意点】
a)【import语句】
-- 【位置】如果源文件包含import语句,那么应该放在package语句和类定义之间。如果没有package语句,那么import语句应该在源文件中最前面。
-- 【作用范围】import语句和package语句对源文件中定义的所有类都有效。在同一源文件中,不能给不同的类不同的包声明
3)【Java Number 类】
a)【产生原因】
在实际开发过程中,我们经常会遇到需要使用对象,而不是内置数据类型的情形。为了解决这个问题,Java 语言为每一个内置数据类型提供了对应的包装类
b)【包装类】
所有的包装类(Integer、Long、Byte、Double、Float、Short)都是抽象类 Number 的子类。
c)【Number子类方法】
4)【Java Character 类】
a)【单个字符】Character 类用于对单个字符进行操作。
b)【代码示例】
// 原始字符 'a' 装箱到 Character 对象 ch 中
Character ch = 'a'; // 原始字符 'x' 用 test 方法装箱
// 返回拆箱的值到 'c'
char c = test('x');
5)【Java String 类】
a)【创建字符串】
String 类有 11 种构造方法,这些方法提供不同的参数来初始化字符串,比如提供一个字符数组参数:
public class StringDemo{
public static void main(String args[]){
char[] helloArray = { 'r', 'u', 'n', 'o', 'o', 'b'};
String helloString = new String(helloArray);
System.out.println( helloString );
}
}
StringDemo.java
b)【不可修改性】
String 类是不可改变的,所以你一旦创建了 String 对象,那它的值就无法改变了。
如果需要对字符串做很多修改,那么应该选择使用 StringBuffer & StringBuilder 类。
6)【Java StringBuffer 和 StringBuilder 类】
a)【可修改】相对String类的不可改变,当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。
b)【区别】
StringBuilder 类速度快,但是不是线程安全的
StringBuffer 类则是 线程安全的,一般建议使用 StringBuilder类,速度快
c)【代码示例】
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);
}
}
StringBuffer
7)【Java 数组】
a)【定义】
-- Java 语言中提供的数组是用来存储固定大小的同类型元素。
-- 相比而言PHP的数组就强大很多,大小不固定,类型也不限制
b)【声明变量】
dataType[] arrayRefVar; // 首选的方法 或 dataType arrayRefVar[]; // 效果相同,但不是首选方法
c)【创建数组】
-- 方法1: Java语言使用new操作符来创建数组
arrayRefVar = new dataType[arraySize];
--方法2:直接创建
dataType[] arrayRefVar = {value0, value1, ..., valuek}; d)【多维数组】
--【定义】: 多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组
--【动态初始化】:
1. 直接为每一维分配空间,如 int a[][] = new int[2][3];
2. 从最高维开始,分别为每一维分配空间
//二维数组动态初始化
String s[][] = new String[2][];
s[0] = new String[2];
s[1] = new String[3];
s[0][0] = new String("Good");
s[0][1] = new String("Luck");
s[1][0] = new String("to");
s[1][1] = new String("you");
s[1][2] = new String("!");
二维数组动态初始化
c)【Arrays 类】
-- 【所属包】java.util.Arrays 类能方便地操作数组,它提供的所有方法都是静态的
-- 【常见方法】赋值(fill), 排序( sort), 比较(equals), 查找(binarySearch)
8)【Java 日期时间】
a)【Date对象】
-- ava.util 包提供了 Date 类来封装当前的日期和时间。 Date 类提供两个构造函数来实例化 Date 对象。
Date对象,提供了toString()等10种方法。
-- 举例:
import java.util.Date;
public class DateDemo {
public static void main(String args[]) {
// 初始化 Date 对象
Date date = new Date();
// 使用 toString() 函数显示日期时间
System.out.println(date.toString());
}
}
DateDemo
b)【SimpleDateFormat类】
-- 【定义】SimpleDateFormat 是一个以语言环境敏感的方式来格式化和分析日期的类。SimpleDateFormat 允许你选择任何用户自定义日期时间格式来运行。
--【举例】
import java.util.*;
import java.text.*;
public class DateDemo {
public static void main(String args[]) {
Date dNow = new Date( );
SimpleDateFormat ft =
new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
System.out.println("Current Date: " + ft.format(dNow));
}
} //输出 Current Date: Sun 2004.07.18 at 04:14:09 PM PDT
SimpleDateFormat
-- 【parse()方法】SimpleDateFormat类的parse()方法可以解析字符串
代码如下:
import java.util.*;
import java.text.*;
public class DateDemo {
public static void main(String args[]) {
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd");
String input = args.length == 0 ? "1818-11-11" : args[0];
System.out.print(input + " Parses as ");
Date t;
try {
t = ft.parse(input);
System.out.println(t);
} catch (ParseException e) {
System.out.println("Unparseable using " + ft);
}
}
}
SimpleDateFormat::parse()
运行结果如下:
$ java DateDemo
1818-11-11 Parses as Wed Nov 11 00:00:00 GMT 1818
$ java DateDemo 2007-12-01
2007-12-01 Parses as Sat Dec 01 00:00:00 GMT 2007
c)【printf方法】
-- printf方法可以很轻松地格式化时间和日期。使用两个字母格式,它以t开头并且以下面表格中的一个字母结尾。
import java.util.Date;
public class DateDemo {
public static void main(String args[]) {
// 初始化 Date 对象
Date date = new Date();
// 显示格式化时间
System.out.printf("%s %tB %<te, %<tY",
"Due date:", date);
}
}
printf
//输出 Current Date/Time : Sat Dec 15 16:37:57 MST 2012
d)【Java 休眠(sleep)】
-- 【作用】sleep()使当前线程进入停滞状态(阻塞当前线程),让出CPU的使用、目的是不让当前线程独自霸占该进程所获的CPU资源,以留一定时间给其他线程执行的机会。
-- 【实现】导包 import java.util.*; 使用 Thread.sleep(1000*3); // 休眠3秒
e)【Calendar类】
-- 【概述】
Calendar类的功能要比Date类强大很多,而且在实现方式上也比Date类要复杂一些。
Calendar类是一个抽象类,在实际使用时实现特定的子类的对象,创建对象的过程对程序员来说是透明的,只需要使用getInstance方法创建即可。
-- 【代码示例】
Calendar c1 = Calendar.getInstance();
// 获得年份
int year = c1.get(Calendar.YEAR);
// 获得月份
int month = c1.get(Calendar.MONTH) + 1;
// 获得日期
int date = c1.get(Calendar.DATE);
// 获得小时
int hour = c1.get(Calendar.HOUR_OF_DAY);
// 获得分钟
int minute = c1.get(Calendar.MINUTE);
// 获得秒
int second = c1.get(Calendar.SECOND);
// 获得星期几(注意(这个与Date类是不同的):1代表星期日、2代表星期1、3代表星期二,以此类推)
int day = c1.get(Calendar.DAY_OF_WEEK);
Calendar
f) 【GregorianCalendar类】
-- 【概述】
Calendar类实现了公历日历,GregorianCalendar是Calendar类的一个具体实现。
Calendar 的getInstance()方法返回一个默认用当前的语言环境和时区初始化的GregorianCalendar对象。GregorianCalendar定义了两个字段:AD和BC。这些代表公历定义的两个时代
-- 【代码示例】
import java.util.*;
public class GregorianCalendarDemo {
public static void main(String args[]) {
String months[] = {
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"};
int year;
// 初始化 Gregorian 日历
// 使用当前时间和日期
// 默认为本地时间和时区
GregorianCalendar gcalendar = new GregorianCalendar();
// 显示当前时间和日期的信息
System.out.print("Date: ");
System.out.print(months[gcalendar.get(Calendar.MONTH)]);
System.out.print(" " + gcalendar.get(Calendar.DATE) + " ");
System.out.println(year = gcalendar.get(Calendar.YEAR));
System.out.print("Time: ");
System.out.print(gcalendar.get(Calendar.HOUR) + ":");
System.out.print(gcalendar.get(Calendar.MINUTE) + ":");
System.out.println(gcalendar.get(Calendar.SECOND));
// 测试当前年份是否为闰年
if(gcalendar.isLeapYear(year)) {
System.out.println("当前年份是闰年");
}
else {
System.out.println("当前年份不是闰年");
}
}
}
GregorianCalendar
9)【Java 正则表达式】
a)【包含3个类】
-- 【Pattern 类】
pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
--【Matcher 类】
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象
--【PatternSyntaxException类】
PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
b)【捕获组】
捕获组是把多个字符当一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。
c)【代码示例】
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*)(\\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");
}
}
}
RegexMatches.java
以上实例编译运行结果如下:
Found value: This order was placed for QT3000! OK?
Found value: This order was placed for QT
Found value: 3000
d)【一些方法】
-- 【Matcher 类的方法】
索引方法:start() end()
10)【Java方法】
a)【可变参数】
方法的可变参数的声明如下所示:
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);
}
}
VarargsDemo.java
b)【finalize() 方法】
-- Java 允许定义这样的方法,它在对象被垃圾收集器析构(回收)之前调用,这个方法叫做 finalize( ),它用来清除回收对象。
--【对象置为空】 c2 = c3 = null;
--【调用Java垃圾收集器】System.gc();
--【父类】super.function()
代码示例如下:
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");
}
}
FinalizationDemo.java
运行以上代码,输出结果如下:
$ 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
运行过程
11)【Java 流(Stream)、文件(File)和IO】
a)【概述】
Java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。
Java.io 包中的流支持很多种格式,比如:基本类型、对象、本地化字符集等等。
一个流可以理解为一个数据的序列。输入流表示从一个源读取数据,输出流表示向一个目标写数据。
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。
b)【控制台输入】
-- Java 的控制台输入由 System.in 完成。
-- 为了获得一个绑定到控制台的字符流,你可以把 System.in 包装在一个 BufferedReader 对象中来创建一个字符流。
例如:
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
-- BufferedReader 对象创建后,我们便可以
使用 read() 方法从控制台读取一个字符,
或者用 readLine() 方法读取一个字符串。
--代码示例如下:
// 使用 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"));
}
}
BRReadLines.java
以上实例编译运行结果如下:
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
注意:JDK 5 后的版本我们也可以使用 Java Scanner 类来获取控制台的输入。
c)【控制台输出】
--【概述】
控制台的输出由 print( ) 和 println() 完成。这些方法都由类 PrintStream 定义,System.out 是该类对象的一个引用。
PrintStream 继承了 OutputStream类,并且实现了方法 write()。这样,write() 也可以用来往控制台写操作。
注意:write() 方法不经常使用,因为 print() 和 println() 方法用起来更为方便。
d)【读写文件】
-- 【概述】
如前所述,一个流被定义为一个数据序列。输入流用于从源读取数据,输出流用于向目标写数据。
下图是一个描述输入流和输出流的类层次图。
-- 【输入流--FileInputStream】
读取数据:该流用于从文件读取数据,它的对象可以用关键字 new 来创建。
有多种构造方法可用来创建对象。
可以使用字符串类型的文件名来创建一个输入流对象来读取文件:
InputStream f = new FileInputStream("C:/java/hello");
或者
File f = new File("C:/java/hello");
InputStream f = new FileInputStream(f);
其他输入流:
-- 【输出流--FileOutputStream】
该类用来创建一个文件并向文件中写数据。
如果该流在打开文件进行输出前,目标文件不存在,那么该流会创建该文件。
有两个构造方法可以用来创建 FileOutputStream 对象
类似输入流,输出流也有两种创建对象的方法。
OutputStream f = new FileOutputStream("C:/java/hello")
或者 File f = new File("C:/java/hello");
OutputStream f = new FileOutputStream(f);
其他输出流:
代码示例:
//文件名 :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();
// 关闭输入流,释放系统资源 }
}
fileStreamTest2.java
--【文件和I/O】
还有一些关于文件和I/O的类,我们也需要知道:
-- 【Java中的目录】
创建文件夹: mkdir( )方法创建一个文件夹
mkdirs()方法创建一个文件夹和它的所有父文件夹。
代码示例如下:
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 是一个目录
12)【 Java 异常处理】
异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。
a)【异常的原因】
-- 异常发生的原因有很多,通常包含以下几大类:
- 用户输入了非法数据。
- 要打开的文件不存在。
- 网络通信时连接中断,或者JVM内存溢出。
b)【异常的分类】
要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:
- 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
- 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
- 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
c)【Exception 类的层次】
所有的异常类是从 java.lang.Exception 类继承的子类。
Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。
d)【Java 内置异常类】
Java 语言定义了一些异常类在 java.lang 标准包中。
标准运行时异常类的子类是最常见的异常类。由于 java.lang 包是默认加载到所有的 Java 程序的,所以大部分从运行时异常类继承而来的异常都可以直接使用。
-- 主要有 非检查性异常 和检查性异常
e)【捕获异常】
-- 【try catch】
使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地方。
try/catch代码块中的代码称为保护代码
-- 【多重捕获】
一个 try 代码块后面跟随多个 catch 代码块的情况就叫多重捕获。
如果保护代码中发生异常,异常被抛给第一个 catch 块。
如果抛出异常的数据类型与 ExceptionType1 匹配,它在这里就会被捕获。
如果不匹配,它会被传递给第二个 catch 块。
如此,直到异常被捕获或者通过所有的 catch 块。
--【throws/throw 关键字】
如果一个方法没有捕获一个检查性异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部。
也可以使用 throw 关键字抛出一个异常,无论它是新实例化的还是刚捕获到的
一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。
--【finally关键字】
finally 关键字用来创建在 try 代码块后面执行的代码块。
无论是否发生异常,finally 代码块中的代码总会被执行。
在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。
finally 代码块出现在 catch 代码块最后
f)【声明自定义异常】
-- 在 Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。
- 所有异常都必须是 Throwable 的子类。
- 如果希望写一个检查性异常类,则需要继承 Exception 类。
- 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
--【只继承Exception类】
只继承Exception 类来创建的异常类是检查性异常类。
--【代码示例】
在下面的 CheckingAccount 类中包含一个 withdraw() 方法抛出一个 InsufficientFundsException 异常。
[1] 自定义异常类InsufficientFundsException,文件名InsufficientFundsException.java
// 文件名InsufficientFundsException.java
import java.io.*; public class InsufficientFundsException extends Exception
{
private double amount;
public InsufficientFundsException(double amount)
{
this.amount = amount;
}
public double getAmount()
{
return amount;
}
}
InsufficientFundsException.java
[2] CheckingAccount 类 文件名称 CheckingAccount.java
// 文件名称 CheckingAccount.java
import java.io.*; public class CheckingAccount
{
private double balance;
private int number;
public CheckingAccount(int number)
{
this.number = number;
}
public void deposit(double amount)
{
balance += amount;
}
public void withdraw(double amount) throws
InsufficientFundsException
{
if(amount <= balance)
{
balance -= amount;
}
else
{
double needs = amount - balance;
throw new InsufficientFundsException(needs);
}
}
public double getBalance()
{
return balance;
}
public int getNumber()
{
return number;
}
}
CheckingAccount.java
[3] 调用类 BankDemo 类 文件名称 BankDemo.java
//文件名称 BankDemo.java
public class BankDemo
{
public static void main(String [] args)
{
CheckingAccount c = new CheckingAccount(101);
System.out.println("Depositing $500...");
c.deposit(500.00);
try
{
System.out.println("\nWithdrawing $100...");
c.withdraw(100.00);
System.out.println("\nWithdrawing $600...");
c.withdraw(600.00);
}catch(InsufficientFundsException e)
{
System.out.println("Sorry, but you are short $"
+ e.getAmount());
e.printStackTrace();
}
}
}
BankDemo.java
[4] 编译上面三个文件,并运行程序 BankDemo,得到结果如下所示:
Depositing $500... Withdrawing $100... Withdrawing $600...
Sorry, but you are short $200.0
InsufficientFundsException
at CheckingAccount.withdraw(CheckingAccount.java:25)
at BankDemo.main(BankDemo.java:13)
编译后运行结果
g)【通用异常】
在Java中定义了两种类型的异常和错误。
- JVM(Java虚拟机) 异常:由 JVM 抛出的异常或错误。例如:NullPointerException 类,ArrayIndexOutOfBoundsException 类,ClassCastException 类。
- 程序级异常:由程序或者API程序抛出的异常。例如 IllegalArgumentException 类,IllegalStateException 类。
13)【Java 重写(Override)与重载(Overload)】
a)【重写(Override)】
-- 【重写规则】
1)参数列表必须完全与被重写方法的相同;
2)返回类型必须完全与被重写方法的返回类型相同;
3)访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为public,那么在子类中重写该方法就不能声明为protected。
4)(父类的成员方法只能被它的子类重写。
5)声明为final的方法不能被重写。
6)声明为static的方法不能被重写,但是能够被再次声明。
7)子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为private和final的方法。
8)子类和父类不在同一个包中,那么子类只能够重写父类的声明为public和protected的非final方法。
9)重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
10)构造方法不能被重写。
11)如果不能继承一个方法,则不能重写这个方法。
重写规则
b)【重载(Overload)】
1)被重载的方法必须改变参数列表(参数个数或类型或顺序不一样);
2)被重载的方法可以改变返回类型;
3)被重载的方法可以改变访问修饰符;
4)被重载的方法可以声明新的或更广的检查异常;
5)方法能够在同一个类中或者在一个子类中被重载。
6)无法以返回值类型作为重载函数的区分标准。
重写规则
c)【重写与重载之间的区别】
方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载是一类中多态性的一种表现。
区别点 | 重载方法 | 重写方法 |
---|---|---|
参数列表 | 必须修改 | 一定不能修改 |
返回类型 | 可以修改 | 一定不能修改 |
异常 | 可以修改 | 可以减少或删除,一定不能抛出新的或者更广的异常 |
访问 | 可以修改 | 一定不能做更严格的限制(可以降低限制) |
【Java学习系列】第2课--Java语法及面向对象的更多相关文章
- Java 8系列之Stream的基本语法详解
本文转至:https://blog.csdn.net/io_field/article/details/54971761 Stream系列: Java 8系列之Stream的基本语法详解 Java 8 ...
- 最新java学习路线:含阶段性java视频教程完整版
最新java学习路线:带阶段性java视频教程版本 第一阶段:Java基础 学习目标: 掌握基本语法.面向对象.常用类.正则.集合.Io流.多线程.Nio.网络编程.JDK新特性.函数式编程 知识点细 ...
- Java 学习(2):java 基础概念
Java作为一种面向对象语言.支持以下基本概念: 多态 继承 封装 抽象 类 对象 实例 方法 重载 基础语法: 一个Java程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作.以 ...
- Java 学习(7):java 日期时间 & 正则表达式
目录 --- 日期时间 --- 正则表达式 日期时间:java.util 包提供了 Date 类来封装当前的日期和时间. Date 类提供两个构造函数来实例化 Date 对象. 构造函数:用于初始化对 ...
- Java 学习(8):java 方法
Java方法是语句的集合,它们在一起执行一个功能. 方法是解决一类问题的步骤的有序组合 方法包含于类或对象中 方法在程序中被创建,在其他地方被引用 命名规则: 1. 必须以 字母.'_'或'$'开头. ...
- Java 学习(9):java Stream & File & IO
Java 流(Stream).文件(File)和IO Java.io 包几乎包含了所有操作输入.输出需要的类.所有这些流类代表了输入源和输出目标. Java.io 包中的流支持很多种格式,比如:基本类 ...
- Java 学习(10):java 异常处理
java 异常处理 异常发生的原因有很多,通常包含以下几大类: 用户输入了非法数据. 要打开的文件不存在. 网络通信时连接中断,或者JVM内存溢出. 三种类型的异常: 检查性异常: 最具代表的检查性异 ...
- Java 学习(21):Java 实例
Java 实例 本章节我们将为大家介绍 Java 常用的实例,通过实例学习我们可以更快的掌握 Java 的应用. Java 环境设置实例 //HelloWorld.java 文件 public cla ...
- 《快乐编程大本营》java语言训练班-第4课:java流程控制
<快乐编程大本营>java语言训练班-第4课:java流程控制 第1节. 顺序执行语句 第2节. 条件分支语句:if条件语句 第3节. 条件分支语句:switch 条件语句 第4节. 条件 ...
- Java 学习(1): windows java 运行& 环境配置
Java 文件的运行 如下,创建了一个 名为"HelloWorld.java" 的 Java 文件: public class HelloWorld { public static ...
随机推荐
- 【Java每日一题】20170105
20170104问题解析请点击今日问题下方的"[Java每日一题]20170105"查看(问题解析在公众号首发,公众号ID:weknow619) package Jan2017; ...
- MySQL,MariaDB:Undo | Redo [转]
本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版 ...
- Configure a bridged network interface for KVM using RHEL 5.4 or later?
environment Red Hat Enterprise Linux 5.4 or later Red Hat Enterprise Linux 6.0 or later KVM virtual ...
- JAVA代码验证身份证信息
java验证身份证信息代码 转自:http://www.blogjava.net/xylz/archive/2011/01/05/342330.html import java.util.Calend ...
- 【已解决】Https请求——基础连接已经关闭 发送时发生错误
本人在做商用项目的推送消息功能时,借助第三方推送服务.这里避免有打广告的嫌疑,就不报名字了.由于是通过调用API接口,所以Post方法是自己写的,但是在开发环境是可以正常推送的,但是一上线就出各种问题 ...
- iOS开发系列--Swift进阶
概述 上一篇文章<iOS开发系列--Swift语言>中对Swift的语法特点以及它和C.ObjC等其他语言的用法区别进行了介绍.当然,这只是Swift的入门基础,但是仅仅了解这些对于使用S ...
- 关于bug分析与异常处理的一些思考
前言:工作三年了,工作内容主要是嵌入式软件开发和维护,用的语言是C,毕业后先在一家工业自动化控制公司工作两年半,目前在一家医疗仪器公司担任嵌入式软件开发工作.软件开发中,难免不产生bug:产品交付客户 ...
- python的拷贝(深拷贝和浅拷贝)
今天看了几篇关于python拷贝的博文,感觉不太清楚,所以我就自己做实验试一下,特此记录. 拷贝是针对组合对象说的,比如列表,类等,而数字,字符串这样的变量是没有拷贝这一说的. 实现拷贝有: 1.工厂 ...
- .net正则表达式大全(.net 的 System.Text.RegularExpressions.Regex.Match()方法使用)
正则表达式的本质是使用一系列特殊字符模式,来表示某一类字符串.正则表达式无疑是处理文本最有力的工具,而.NET的System.dll类库提供的System.Text.RegularExpression ...
- HTML5_04之SVG绘图
1.关于Canvas绘制图像: 问题:需要绘制多张图片时,必须等待所有图片加载完成才能开始绘制:而每张图片都是异步请求,彼此没有先后顺序,哪一张先加载完成完全无法预测: 方案: var progres ...