Java高級教程
阿新 • • 發佈:2019-01-16
eth 被調用 管理 rst 年齡 rgs 接口的應用 權限 文件讀寫
1. 處理流:
目錄
- 1.Java面向對象方法
- 1.1. 創建類和對象的方法
- 1.2. this的使用
- 1.3. 靜態域和靜態方法
- 1.3.1. 靜態域:屬於類的級別
- 1.3.2.靜態常量
- 1.3.3 靜態方法
- 1.3.4. 工廠方法
- 1.3.5. main方法
- 1.4. 對象構造
- 1.4.1. 對象重載
- 1.4.2. 類的構造器以及初始化
- 1.5. 包
- 2. Java的繼承
- 2.1. 繼承的語法
- 2.2. 繼承中的對象轉型
- 2.2.1. 對象向上轉型
- 2.2.2. 對象向下轉型
- 2.3. 阻止繼承:final類和方法
- 2.4.抽象類和抽象函數
- 2.4.1. 定義方法與語法特征
- 2.4.2. 為什麽用抽象類?
- 3. 包的訪問權限
- 3.1. 將類放到包中
- 3.2. 包的訪問權限有哪些
- 4. 接口
- 4.1. 什麽是接口
- 4.2.接口語法
- 4.3. 接口的應用
- 5. Java的異常處理
- 5.1. JDK異常的分類和try-catch捕捉
- 5.2. 用戶自定義的異常處理
- 6. Java中的IO
- 6.1. IO的定義和分類,以及字節流基本用法:
- 6.2. 大文件的讀寫方法和字符流的使用
- 1. 大文件讀寫
- 2.字符流
- 6.3. 節點流和處理流
- 1. 處理流:
BufferedReader
:字符輸入處理流
- 1. 處理流:
- 7.內部類和匿名內部類
- 7.1. 內部類
- 7.2. 匿名內部類
1.Java面向對象方法
- 繼承
- 封裝
- 多態
this的用法
- 引用隱式參數
- 調用該類其他的構造器
super的用法
- 調用超類方法
- 調用超類的構造器
1.1. 創建類和對象的方法
對象和引用的一個關系圖:
模板:
class ClassName {
field1 // 屬性: 描述類的狀態
field2
...
constructor1
constructor2
...
method1 // 方法: 描述類的行為
method2
}
下面是一個簡單的實例
public class Main { public static void main(String[] args) throws IOException { // 對象的使用方法 // 對象.變量: staff.name // 對象.函數(): staff.getname() Employee[] staff = new Employee[3]; staff[0] = new Employee("Zhang", 75000, 1977, 12,15); staff[1] = new Employee("Li", 23000, 1932, 3,5); staff[2] = new Employee("Zhang", 56444, 1964, 6,21); for (Employee e: staff){ e.raiseSalary(5); } for (Employee e: staff){ System.out.println("name=" + e.getName() + ", salary=" + e.getSalary() + ", hireday=" + e.getHireDay()); } } } // 一個類可以有無限多個對象 class Employee{ // 三個實例域用來存放將要操作的數據 private String name; private double salary; private LocalDate hireDay; // 構造器(與類名同名),總是伴隨著new操作符的執行而被調用 // 每個類可以有一個以上的構造器 // 如果類中沒有構造器,java會默認有一個構造器用於初始化 // 但是如果類的構造器大於1個的話,需要自己構造默認構造器 // 構造器可以有0,1,...等多個參數 // 構造器沒有返回值,即沒有void // 構造器總是伴隨著new的操作一起調用 public Employee(String n, double s, int year, int month, int day){ name = n; salary = s; hireDay = LocalDate.of(year, month, day); } // 需要獲得或者設置實例域的值,需要提供以下三個內容: // (1).一個私有的數據域 // (2).一個公有的域訪問器方法 // (3).一個公有的域更改器方法 public String getName() { return name; } public double getSalary() { return salary; } public LocalDate getHireDay() { return hireDay; } public void setHireDay(LocalDate hireDay) { this.hireDay = hireDay; } public void setName(String name) { this.name = name; } public void setSalary(double salary) { this.salary = salary; } // class方法有兩個參數: 顯示參數(括號內部的參數) + 隱式參數(引用該方法的對象) // 用this來表示隱式參數,表示使用該方法的對象 public void raiseSalary(double rate){ // 可以直接訪問類的屬性 double raise = this.salary * rate / 100; this.salary = this.salary + raise; } }
1.2. this的使用
- 使用this調用成員變量和成員函數
- 使用this調用構造函數
class Person{
String name;
int age;
String address;
Person(){
System.out.println("無參數");
}
Person(String s, int a){
this.nanme = s;
this.age = a;
}
// this可以調用構造函數
Person(String s, int a, String s2){
this(s, a);
this.address = s2;
}
// this為使用該方法的對象,也稱為類的隱式參數
void talk(){
System.out.println("my name is " + this.name)
}
}
1.3. 靜態域和靜態方法
1.3.1. 靜態域:屬於類的級別
- 一般變量:
對象.變量
- 靜態變量:
類名.變量
+對象.變量
如果將一個域定義為static, 每個類中只有一個這樣的域, 而每個對象對於所有的實例域卻有自己的一份拷貝, 比如我們創建一個class:
class Employee {
private static int nextID = 1;
private int id;
}
如果有1000getEmployee類的對象,就有100個實例域id,但是只有一個靜態域nextId
1.3.2.靜態常量
// 1000個對象有1000個拷貝
public final double PI = 3.14;
// 1000個對象只有一個PI
public static final doube PI = 3.14;
1.3.3 靜態方法
靜態方法是一種不能向對象實施操作的方法,只能通過類名調用,也就是說沒有this隱式參數
- 非靜態方法:
employee.getNextID()
- 靜態方法:
Employee.getNextID()
- 靜態函數中不能使用非靜態變量(非靜態域)
1.3.4. 工廠方法
1.3.5. main方法
public class Main {
// main是一個靜態方法,不對任何對象進行操作
// 事實上,再啟動程序的時候沒有任何對象,靜態main方法將執行並創建程序需要的對象
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
1.4. 對象構造
1.4.1. 對象重載
如果多個方法有相同的名字、不同的參數,便產生了重載,編譯器根據傳入的參數自動旋轉哪個方法
StringBuilder msg = new StringBuilder();
StringBuilder msg = new StringBuilder("To do: \n");
1.4.2. 類的構造器以及初始化
class Employee {
private static int nextId;
private int id;
private String name;
private double salary;
//初始化塊中初始化值
{
id = nextId;
nextId++;
}
// 構造器中初始化值
public Employee(){
name = ""
salary=0;
}
public Employee(String n, double s){
this.name = name;
this.salary = s;
}
}
1.5. 包
管理class文件的
- 導入類文件:
import java.util.*
- 將類文件放到包中:
package com.horstman.corejava
2. Java的繼承
一個類得到了另外一個類的成員變量和成員函數
Java只支持單繼承,不允許多繼承
2.1. 繼承的語法
public class Main {
public static void main(String[] args) {
// 生成子類的過程
student st = new student("zhang", 20, 6);
st.introduce();
}
}
// 將重復代碼放到父類中去
class Person{
String name;
int age;
public Person(){
System.out.println("Person無參數");
}
public Person(String name, int age){
this.name = name;
this.age = age;
}
void eat(){
System.out.println("吃飯");
}
void introduce(){
System.out.println("my name is " + this.name + ", my age is " + this.age);
}
}
class student extends Person{
int grade;
// 自動繼承父類的成員變量和成員函數
// 在子類的構造函數中,必須調用父類的構造函數
public student(String name, int age, int grade) {
super(name, age);
this.grade = grade;
}
// 子類可以寫自己的成員函數
void study(){
System.out.println("Study");
}
// 復寫 父類的方法
// 1. 在具有父子關系的兩個類當中
// 2. 父類和子類中各有一個函數,這兩個函數的定義(返回值類型,函數名和參數列表)完全相同
@Override
void introduce() {
super.introduce();
System.out.println("my grade is " + this.grade);
}
}
2.2. 繼承中的對象轉型
2.2.1. 對象向上轉型
將子類的對象賦值給父類的引用
// s是學生,也是人
//s: 變量(name,age,address) + 函數(introduce, study)
Student s = new Student();
//p:變量(name,age) + 函數(introduce)
Person p = s;
// 一個引用能夠調用哪些成員變量和函數,取決於這個引用的類型(p引用person,看p前面的類型)
// 一個引用調用的哪個方法,取決於這個引用所指向的對象(p指向的是student對象,調用student方法)
p.name = "zhang";
p.age = 12;
// p.address = "bj" 不可以使用(他說)
p.introduce(); // 調用的是子類的Introduce()
// p.study() 不可以使用
2.2.2. 對象向下轉型
Student s1 = new Student();
Person p = s1;
Student s2 = (Student)p;
2.3. 阻止繼承:final類和方法
- 將類定義為final後,無法繼承
- 將類的方法定義為final後,子類無法覆蓋該方法
public class final Mother extends Person{
....;
}
public class student extends Person{
public final String getName{
....;
}
}
2.4.抽象類和抽象函數
面向對象思想:先抽象,後具體
2.4.1. 定義方法與語法特征
- 只有函數的定義,沒有函數體的函數
- 抽象類不能生成對象(如果能的話,可能調用抽象函數,但是抽象函數沒有函數體,無法解釋)
- 抽象類天生是當爹的,只能被繼承,它的子類可以生成對象
- 如果一個類中包含抽象函數,那麽類必須被聲明為抽象類
- 如果一個類中沒有抽象函數,也可以聲明為抽象類
- 抽象類可以有構造函數
public class Main {
public static void main(String[] args) {
Person p = new Chinese();
p.eat();
}
}
// 抽象類
abstract class Person{
String name;
int age;
public Person(){
System.out.println("Person無參數");
}
public Person(String name, int age){
this.name = name;
this.age = age;
}
// 抽象函數
abstract void eat();
void introduce(){
System.out.println("my name is " + this.name + ", my age is " + this.age);
}
}
class Chinese extends Person{
Chinese(){
super();
System.out.println("chinese的構造函數");
}
@Override
void eat() {
System.out.println("用筷子吃飯");
}
}
2.4.2. 為什麽用抽象類?
- 抽象類表達的是一種抽象的概念,屬於比父類還抽象的類
- 抽象函數可以檢查子類是否復寫了抽象函數,是一種檢測機制,檢測是否子類有沒有寫應該復寫的抽象函數
public class Main {
public static void main(String[] args) {
Person[] p = new Person[2];
p[0] = new Employee("zhang",5000,2018,10,12);
p[1] = new Student("Li", "CS");
// i.getDescription()中由於不能構造抽象類Person的對象,所以變量i永遠不會引用person對象,而是引用employee或者student子類的具體對象
for (Person i:p){
System.out.println(i.getName() + "," + i.getDescription());
}
}
}
// 將重復代碼放到父類中去
abstract class Person{
abstract String getDescription();
String name;
Person(String name){
this.name=name;
}
public String getName() {
return name;
}
}
class Employee extends Person{
double salary;
LocalDate hireday;
Employee(String name,double salary, int year, int month, int day){
super(name);
this.salary = salary;
hireday = LocalDate.of(year,month, day);
}
public double getSalary() {
return salary;
}
@Override
public String getName() {
return super.getName();
}
public LocalDate getHireday() {
return hireday;
}
@Override
String getDescription() {
return String.format("an employee with a salary of %.2f", salary);
}
}
class Student extends Person{
String major;
Student(String name, String major){
super(name);
this.major = major;
}
@Override
public String getName() {
return super.getName();
}
public String getMajor() {
return major;
}
@Override
String getDescription() {
return "a student majoring in" + major;
}
}
zhang,an employee with a salary of 5000.00
Li,a student majoring inCS
3. 包的訪問權限
3.1. 將類放到包中
什麽是軟件包?
怎麽講類放到軟件包中?
- 將類放到一個包中,需要使用packcage “包名”
- 編譯時需要使用 -d參數,該參數的作用是依照包名生成相應的文件夾
- 一個類的全名: 包名 + . + 類名:mars.Test
- 包名的命名規範
- 一般小寫
- 一般是域名倒過來寫:
io.github.com.haochen95
;
- 一般小寫
package mars;
class Test{
public static void main(String[] args){
System.out.println("package")
}
}
3.2. 包的訪問權限有哪些
訪問權限 | 含義 | 包內可否使用 | 包之間可否使用 | 包內繼承 | 包間繼承 |
---|---|---|---|---|---|
public | 公有權限 | Yes | Yes | Yes | Yes |
private(很少修飾類) | 私有權限 | No | No | No | No |
default | 包級別訪問權限 | Yes | No | Yes | No |
protected(不修飾類) | 受保護權限 | Yes | No | Yes | Yes(只有子類才能使用) |
- 如果子類和父類不在同一個包中,子類確實繼承到了父類的成員變量和成員函數,然後再檢查權限,看是否能夠使用
public > protected > default > private
4. 接口
4.1. 什麽是接口
4.2.接口語法
- 使用Interface定義
- 接口中的方法全是抽象方法
- 接口中的方法全是public權限
- 實現接口使用implements關鍵字
- 一個類可以實現多個接口
- 一個接口可以繼承多個接口
// 定義接口
interface USB{
public void read();
public void write();
}
interface WIFI{
public void open();
public void close();
}
// 繼承接口
class Phone implements USB,WIFI{
public void read(){
System.out.println("USB READ")
}
public void write(){
System.out.println("USB WRUTE")
}
public void open(){
System.out.println("WIFI OPEN")
}
public void close(){
System.out.println("WIFI CLOSE")
}
}
// 主函數中調用
class Test{
public static void main(String[] args){
Phone phone = new Phone();
USB usb = phone;
usb.read();
usb.write();
WIFI wifi = phone;
wifi.open();
wifi.close();
}
}
4.3. 接口的應用
- 在繼承中,可以將重復代碼放到父類中
- 但是所有子類都需要使用類似的方法體,可能使用接口更加的合適
- 接口定義了一種標準,接口只定義應該有這些方法,但是不關心方法的具體實現方法,由每個子類自己去實現
5. Java的異常處理
5.1. JDK異常的分類和try-catch捕捉
- 異常:終端了正常指令流的事件;
- 程序在異常處會中斷,退出程序
- 使用try-catch捕捉異常(對於track error必須使用)
try{
System.out.println(4); // 沒出異常,繼續執行/出了異常跳到catch執行,再繼續執行
}
catch(Exception e){
e.printStackTrace();
System.out.println(5);
}
finally{ // 異常出不出 都會執行這個程序-----主要用於IO流的關閉文件代碼
System.out.println(6);
}
System.out.println(7);
5.2. 用戶自定義的異常處理
- throw和throws關鍵字的用法
public void setAge(int age){
if(age<0){
// untrack excaption---程序運行到這裏就會終止
RuntimeException e = new RuntimeException("年齡不能為負數");
throw e;
// track excaption --- 必須用try-catch進行捕捉或者聲明(throws Exception)放在類聲明中
Exception e = new Exception("年齡不能為負數")
throw e;
}
}
6. Java中的IO
6.1. IO的定義和分類,以及字節流基本用法:
- IO的目標:從數據源(文件,鍵盤,網絡)中讀取數據,從數據寫入到數據目的地(文件,屏幕,網絡)當中
- 輸入和輸出流在Java中都設置成一種"管道", IO流也是一種對象
- IO的分類
- 輸入輸出流
- 字節流,字符流
節點流,處理流
IO流中的核心類:
InputStream(抽象類) <- FileInputStream
,OutputStream(抽象類) <-FileoutputStream
-InputStream: int read(byte[] b, int off, int len)
,返回讀取了多少字節的數據
-OutputStream: void write(byte[] b, int off, int len)
import java.io.*;
// 字節流
class Test{
public static void main(String[] args){
// 聲明輸入流引用
FileInputStream fis = null;
// 聲明輸出流引用
FileoutputStream fos = null;
try{
// 字節流-讀數據: 生成代表輸入流的對象
fis = new FileInputStream("D:/from.txt");
// 生成代表輸出流的對象
fos = new FileoutputStream("D:/to.txt");
// 生成一個字節數組
byte[] buffer = new byte[100];
// 調用輸入流的read方法,讀取數據
int temp = fis.read(buffer, 0, 100);
// 寫入到文件中
fos.write(buffer,0, temp);
String s = new String(buffer); // 將字節轉為字符
// 去除空格
s = s.trim();
System.out.println(s);
}
catch(Exception e){
System.out.println(e);
}
}
}
6.2. 大文件的讀寫方法和字符流的使用
1. 大文件讀寫
import java.io.*;
class Test{
public static void main(String[] args){
FileInputStream fis = null;
FileoutputStream fos = null;
try{
fis = new FileInputStream("D:/from.txt");
fos = new FileoutputStream("D:/to.txt");
byte[] buffer = new byte[100];
// 大文件:循環讀取
while(true){
int temp = fis.read(buffer, 0, 100);
// 讀到文件最後的時候,read返回-1
if (temp == -1){
break;
}
fos.write(buffer,0, temp);
}
}
catch(Exception e){
System.out.println(e);
}
finally{
// 一定要在finally中關閉文件管道
try{
fis.close();
fos.close();
}
catch(Exception e){
System.out.println(e);
}
}
}
}
2.字符流
- 讀寫文件是,以字符為基礎
- 核心方法:
Reader(抽象類) <- FileReader
,Writer(抽象類) <-FilWriter
-Reader: int read(char[] b, int off, int len)
,返回讀取了多少字節的數據
-Writer: void write(char[] b, int off, int len)
import java.io.*;
class Test{
public static void main(String[] args){
FileReader fr = null;
FilWriter fw = null;
try{
fr = new FileReader("D:/from.txt");
fw = new FIleWriter("D:/to.txt");
char[] buffer = new char[100];
int temp = fr.read(buffer,0,buffer.length);
}catch(Exception e){
System.out.println(e);
}
finally{
// 一定要在finally中關閉文件管道
try{
fr.close();
fw.close();
}
catch(Exception e){
System.out.println(e);
}
}
}
}
6.3. 節點流和處理流
1. 處理流: BufferedReader
:字符輸入處理流
readline
功能
- 生成BufferedReader對象的方法:
BufferedReader in = new BufferedReader(new FileReader("D:/from.txt"))
import java.io.*; class Test{ public static void main(String[] args){ FileReader fileReader = null; BufferedReader bufferedReader = null; try{ fileReader = new FileReader("D:/from.txt"); bufferedReader = new BufferedReader(fileReader); // 按照一行一行的讀取 Strign line = null; while(true){ line = bufferedReader.readline(); if (line == null){ break; } // 打印每一行 System.out.println(line) } } catch(Exception e){ System.out.println(e); } finally{ // 一定要在finally中關閉文件管道 try{ fileReader.close(); bufferedReader.close(); } catch(Exception e){ System.out.println(e); } } } }
7.內部類和匿名內部類
7.1. 內部類
- 生成內部類的對象:
A.B b = new A().new B();
class A{
int i;
// 內部類:A&B.class
class B{
int j;
int funB(){
// 內部類可以隨意使用外部類的變量
int result = i+j;
return result;
}
}
}
class test{
public static void main(String[] args){
// 生成內部類的對象
A a =new A();
A.B b = new A().new B();
a.i = 3;
b.j = 1;
b.funB(); // 結果是 3 + 1 = 4;
}
}
7.2. 匿名內部類
interface A{
public void dosomething{};
}
class B{
public void fun(A a){
System.out.println("B lei");
a.dosomething();
}
}
class Test{
public static void main(String[] args){
B b = new B();
// 利用匿名內部類 來繼承父類或者實現接口
b.fun(new A(){
public vod dosomething(){
System.out.println("Do domething");
}
})
}
}
Java高級教程