Java學習筆記(1)面向物件
1、Java面向物件中類與物件的概念和使用
方法的定義:
方法就是一段可以重複呼叫的程式碼。
定義格式:
訪問修飾符 返回值型別 方法名(){
方法主體
}
方法的返回值型別:
void型別不需要返回值,其他型別的全部需要返回值。
方法的過載:
方法名稱不同,但是引數的型別和個數相同,通過傳遞引數的個數和型別不同來完成不同的功能。
類的定義:
class 類名稱{
屬性
方法
}
宣告一個類需要通過一個關鍵字class。
類與物件的關係:
類是對某一類事物的描述,是抽象的、概念上的意義,物件是實際存在的該類事物的每一個個體,也被稱為物件或例項。
瞭解面向物件:
1、程式的發展歷程:面向過程、面向物件。
2、解釋面向過程和麵向物件:(比如製作一個盒子)
- 面向過程:不去想做什麼樣子的盒子,隨機取工具製作。
- 面向物件:先想好做一個什麼樣的盒子,再去找對應的工具去做。
面向物件的三大特徵:
- 封裝性:對外部不可見。
- 繼承:擴充套件類的功能。
- 多型性:方法的過載。 物件的多型性。
方法的遞迴:
遞迴呼叫就是方法自己呼叫自己。
例如:求1-100的和。
package java面向物件;
public class 遞迴呼叫 {
public static void main(String[] args) {
System.out.println(sum(100 ));
}
//求1-100的和
public static int sum(int n){
if (n == 1) //程式出口
return 1;
else
return n+sum(n-1);
}
}
2、Java面向物件的基本特徵之一:封裝性
封裝性:
1、封裝性的目的:保護某些屬性和方法不被外部所看見。
2、封裝的實現:為屬性和方法進行封裝是通過關鍵字private宣告的。 實現該屬性的set和get方法,為外部所訪問。
例如:
package java面向物件;
//private 實現分裝,外部不可直接呼叫。
//get set 是外界訪問的介面。
class Person{
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
if (age>=0 && age<150) { //判斷年齡是否合法。若非法顯示為0
this.age = age;
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void tell(){ //get是得到
System.out.println("姓名:"+getName()+" 年齡:"+getAge());
}
}
public class 封裝性 {
public static void main(String[] args) {
Person per = new Person();
per.setName("張三");//set是設定
per.setAge(30);
per.tell();
}
}
匿名物件:
匿名物件就是沒有名字的物件,如果程式中只用一次該物件,就可以事業匿名物件的方式。
例如:
package java面向物件;
class Student{
public void tell() {
System.out.println("hello");
}
}
public class 匿名物件 {
public static void main(String[] args) {
//正常物件
Student stu = new Student();
stu.tell();
//匿名物件
new Student().tell();//呼叫一次的情況可用匿名物件
}
}
構造方法:
1、格式:
訪問修飾符 類名稱(){
程式語句
}
2、注意點:
- 構造方法名稱必須與類名一致。
- 構造方法沒有返回值。
3、構造方法主要是為類中的屬性初始化。
4、每個類在例項化之後都會呼叫構造方法,如果沒有構造方法,程式在編譯的時候回建立一個無參的什麼都不做的構造方法。
5、構造方法也可以過載。
例如:
package java面向物件;
class People{
//構造方法
public People(int a) {
System.out.println(a);
}
}
public class 構造方法 {
public static void main(String[] args) {
People per = new People(5);
}
}
3、Java面向物件中引用的傳遞
引用傳遞:
也稱為傳地址。方法呼叫時,實際引數的引用(地址,而不是引數的值)被傳遞給方法中相對應的形式引數,在方法執行中,對形式引數的操作實際上就是對實際引數的操作,方法執行中形式引數值的改變將會影響實際引數的值。
值傳遞:
方法呼叫時,實際引數把它的值傳遞給對應的形式引數,方法執行中形式引數值的改變不影響實際參 數的值。
例如:
package java面向物件;
class Ref{
String temp = "hello";
}
public class 引用傳遞 {
public static void main(String[] args) {
Ref r1 = new Ref();
System.out.println(r1.temp);
tell(r1);
System.out.println(r1.temp);
}
public static void tell(Ref r1) {
r1.temp = "word";
}
}
this關鍵字:
- 表示類中的屬性和呼叫方法。
- 呼叫本類中的構造方法。
- 表示當前物件。
package java面向物件;
class People1{
String name;
int age;
public People1(String name,int age) {
this(); //this作用二:呼叫本類中構造方法
//注意:使用此呼叫,必須放在第一行
this.name=name; //this作用一:呼叫本類中屬性name
this.age=age;
}
private People1() {
System.out.println("呼叫無參構造方法");
}
public void tell() {
System.out.println("姓名:"+this.name+" 年齡:"+this.age);
System.out.println(this); //this作用三:表示當前物件
}
}
public class this關鍵字 {
public static void main(String[] args) {
People1 p = new People1("張三",30);
p.tell();
}
}
static關鍵字:
- 使用static宣告屬性:static宣告全域性屬性。
- 使用static宣告方法:直接通過類名呼叫。
- 注意點:使用static方法的時候,只能訪問static宣告的屬性和方法,而非static宣告的屬性和方法是不能被訪問的。
4、Java面向物件基本特徵:繼承
繼承的實現:
- 繼承的基本概念:擴充套件父類的功能。
- Java中使用extends關鍵字完成繼承。 class 子類 extends 父類 {}
例如:
package java面向物件;
class People2{
String name;
int age;
public void tell() {
System.out.println("姓名:" +name+ "年齡:"+age);
}
}
//學生為人的子類,可以繼承人的屬性,姓名,年齡
class Student2 extends People2{
int score;
public void say() {
System.out.println("成績:"+score);
}
}
public class 繼承 {
public static void main(String[] args) {
Student2 s = new Student2();
s.age = 15;
s.name = "小明";
s.score = 89;
s.tell();
s.say();
}
}
繼承的限制:
- 在Java中只允許單繼承。
- 子類不能直接訪問父類的私有地址。
例如:
package java面向物件;
//只能進行單繼承
//子類不能直接訪問父類的私有地址。
class People3{
private int age; //封裝為私有屬性
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
class Worker extends People3{ //Worker單繼承People3
}
class PetWorker extends Worker{ //PetWorker單繼承Worker
public void tell(int age) {
setAge(age); //子類通過get和set可呼叫父類私有地址
System.out.println(getAge());
}
}
public class 繼承的限制 {
public static void main(String[] args) {
PetWorker p = new PetWorker();
p.tell(30);
}
}
子類物件的例項化:
在子類物件例項化之前,必須先呼叫父類中的構造方法,之後呼叫子類的構造方法。
例如:
package java面向物件;
class Father{
public Father() {
System.out.println("父類的構造方法");
}
}
class Son extends Father{
public Son() {
System.out.println("子類的構造方法");
}
}
public class 子類物件的例項化 {
public static void main(String[] args) {
Son s =new Son(); //宣告並例項化
}
}
程式執行結果:
父類的構造方法
子類的構造方法
繼承方法的重寫:
- 在繼承中,也存在著重寫的概念,其實就是定義了和父類同名的方法。
- 定義:方法名稱相同,返回值類相同,引數也相同。
- 重寫的限制:被子類重寫的方法不能擁有比父類更加嚴格的訪問許可權。
- 訪問許可權:private
public、private、protected、default的區別:
首先就class之間的關係做一個簡單的定義,對於繼承自己的class,base class可以認為他們都是自己的子女,而對於和自己一個目錄下的classes(即同一個包),認為都是自己的朋友friendly。
- public:public表明該資料成員、成員函式是對所有使用者開放的,所有使用者都可以直接進行呼叫
- private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用,私有財產神聖不可侵犯嘛,即便是子女,朋友,都不可以使用。
- protected:protected對於子女、朋友來說,就是public的,可以自由使用,沒有任何限制,而對於其他的外部class,protected就變成private。
- default:java的預設訪問許可權,當沒有使用上面提到的任何訪問限定詞時,就使用它,這種許可權通常被稱為包訪問許可權,在這種許可權下,類可以訪問在同一個包中的其他類的成員,也即可以訪問我們前面說的朋友,在包之外,這些成員如同指定了private。
java 變數作用域的修飾的作用範圍:
- public:類本身和任何包的任何類都訪問
- private 只有類本身可以訪問,其他類想訪問可以通過該類的成員方法訪問如getter/setter
- protected:保護的,這個和預設的比較容易混淆,記住最主要區別是:protected可以在不同包的子類被訪問,而friendly不可以。 protected可以在類本身、同包的子類,不同包的子類,同包的非子類 被訪問
- 預設的:可以在類本身,同包的子類,同包的非子類 被訪問。
同類 | 同包 | 不同包子類 | 不同包非子類 |
---|---|---|---|
private | √ | ||
default | √ | √ | |
protected | √ | √ | √ |
public | √ | √ | √ |
super關鍵字:
強行呼叫父類的方法的執行。
super不一定在重寫中使用,也可以表示哪些方法是從父類中繼承而來的。
例如:
package java面向物件;
class A{
void tell() {
System.out.println("父類的構造方法");
}
}
class B extends A{
void tell() { //方法的重寫
super.tell(); //super強行呼叫父類的方法的執行
System.out.println("子類的構造方法");
}
}
public class 繼承方法的重寫 {
public static void main(String[] args) {
B b = new B();
b.tell();
}
}
程式執行結果:
父類的構造方法
子類的構造方法
重寫與過載的區別:(重點)
NO | 區別點 | 過載 | 重寫 |
---|---|---|---|
1 | 單詞 | Overloading | Overriding |
2 | 定義 | 方法名稱相同,引數的型別和個數不同 | 方法名稱、引數的型別個數、返回值全部相同 |
3 | 許可權要求 | 對許可權沒要求 | 被重寫的方法不能有比父類更加嚴格的許可權 |
4 | 範圍 | 發生在一個類中 | 發生在繼承中 |
5、Java面向物件-抽象類與介面
final關鍵字:
1、final關鍵字在java中被稱為完結器,表示終結的意思。
2、final使能宣告類、方法。屬性:
- 使能final宣告的類不能被繼承。
- 使能final宣告的方法不能被重寫。
- 使能final宣告的變了變成常量。常量是不可以被修改的。
抽象類:
抽象類概念:包含一個抽象方法的類就是抽象類。
抽象方法:宣告而未被實現的方法,抽象方法必須使用abstract關鍵字宣告。
抽象類被子類繼承,子類(如果不是抽象類)必須重寫抽象類中的所有抽象方法。
定義格式:
abstract class className{ 屬性 方法 抽象方法 }
抽象類不能直接例項化,要通過其子類進行例項化。
例如:
package java面向物件;
abstract class Abs{ //抽象類也必須使用abstract宣告
int age;
private void tell() {
}
//抽象方法,宣告而未被實現的方法
public abstract void say();
}
class C extends Abs{
//抽象類被子類繼承,子類(如果不是抽象類)必須重寫抽象類中的所有抽象方法。而且方法必須實現。
public void say() {
System.out.println(20);
}
}
public class 抽象類 {
public static void main(String[] args) {
// Abs a = new Abs(); //抽象類不能被直接例項化
C c = new C(); //抽象類必須通過子類例項化
c.say();
}
}
介面的實現:
介面是Java中最重要的概念、介面可以理解為一種特殊的類,裡面全部是由全域性常量和公共的抽象方法所組成的。
介面的格式:
interface interfaceName{ 全域性常量 抽象方法 }
介面的實現也必須通過子類,使用關鍵字implments,而且介面是可以多實現的。
一個子類可以同時繼承抽象類和實現多介面。
一個介面不能繼承一個抽象類,但是卻可以通過extends關鍵字同時繼承多個介面,實現介面的多繼承。
例如:
package java面向物件;
interface Ineter1{ //定義了一個介面1
public static final int AGE = 20; //定義全域性常量,全域性常量名稱必須全部大寫
public abstract void tell(); //定義一個抽象方法
}
interface Inter2{ //定義介面2
public abstract void say();
}
abstract class Abs3{ //定義抽象類
public abstract void print();
}
//一個子類同時繼承抽象類和實現多介面
class D extends Abs3 implements Ineter1,Inter2{
public void tell() {} //複寫介面內的抽象方法
public void say() {}
public void print() {}
}
//一個介面不能繼承一個抽象類,但是卻可以通過extends關鍵字同時繼承多個介面,實現介面的多繼承
interface Inter3 extends Inter2,Ineter1{
}
public class 介面的實現 {
public static void main(String[] args) {
//Inetr1 i = new Inetr1(); //介面的例項化必須通過子類。
D d= new D(); //例項化介面
d.tell();
d.say();
System.out.println(Ineter1.AGE);
}
}
6、Java面向物件多型性
多型性:
1、多型性的體現:方法的過載和重寫。 物件的多型性。
2、物件的多型性:
- 向上轉型:程式會自動完成。 父類 父類物件 = 子類例項
- 向下轉型:強制型別轉換。 子類 子類物件 = (子類)父類例項
例如:
package java面向物件;
//多型性的體現:方法的過載和重寫。 物件的多型性。
class I{
public void tell1() {
System.out.println("I--tell1");
}
public void tell2() {
System.out.println("I--tell2");
}
}
class J extends I{
public void tell1() {
System.out.println("J==tell1");
}
public void tell3() {
System.out.println("J==tell3");
}
}
public class 多型性 {
public static void main(String[] args) {
//向上轉型 程式會自動完成。 父類 父類物件 = 子類例項
// J j = new J();
// I i = j;
// i.tell1(); //執行tell1重寫的
// i.tell2();
//向下轉型:強制型別轉換。 子類 子類物件 = (子類)父類例項
//必須先向上轉型,才能向下轉型
I i = new J(); //是對向上轉型的縮寫
J j = (J)i;
j.tell1();
j.tell2();
j.tell3();
}
}
程式執行結果:
J==tell1
I--tell2
J==tell3
instanceof關鍵字:
- instanceof 運算子是用來在執行時指出物件是否是特定類的一個例項。instanceof通過返回一個布林值來指出,這個物件是否是這個特定類或者是它的子類的一個例項。
- 用法:result = object instanceof class
- 引數:
- Result:布林型別。
- Object:必選項。任意物件表示式。
- Class:必選項。任意已定義的物件類。
- 說明:
如果 object 是 class 的一個例項,則 instanceof 運算子返回 true。如果 object 不是指定類的一個例項,或者 object 是 null,則返回 false。
例如:
package java面向物件;
class A2{
}
class B2 extends A2{
}
public class instanceof關鍵字 {
public static void main(String[] args) {
A2 a2 = new A2();
System.out.println(a2 instanceof A2);
System.out.println(a2 instanceof B2);
//向上轉型
A2 a3 = new B2();
System.out.println(a3 instanceof A2);
System.out.println(a3 instanceof B2);
}
}
程式執行結果:
true
false
true
true
抽象類的應用舉例:
package java面向物件;
abstract class Person1{
private int age;
private String name;
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Person1(String name,int age){
this.name = name;
this.age = age;
}
public abstract void want();
}
class Student1 extends Person1{
private int score;
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public Student1(String name,int age,int score) {
super(name, age);
this.score = score;
}
public void want() {
System.out.println("姓名:"+getName()+" 年齡:"+getAge()+" 工資:"+getScore());
}
}
class Worker2 extends Person1{
private int maney;
public void setManey(int maney) {
this.maney = maney;
}
public int getManey() {
return maney;
}
public Worker2(String name, int age, int maney) {
super(name, age);
this.maney = maney;
}
public void want() {
System.out.println("姓名:"+getName()+" 年齡:"+getAge()+" 工資:"+getManey());
}
}
public class 抽象類的應用 {
public static void main(String[] args) {
Student1 s = new Student1("小明", 10, 100);
s.want();
Worker2 w = new Worker2("小明",30, 3000);
w.want();
}
}
程式執行結果:
姓名:小明 年齡:10 工資:100
姓名:小明 年齡:30 工資:3000
介面的應用舉例:
package java面向物件;
interface USB{ //定義一個USB介面
void start(); //定義抽象方法
void stop();
}
class Computer{
public static void work(USB u) {
u.start();
System.out.println("工作中···");
u.stop();
}
}
class USBDesk implements USB{ //定義一個U盤裝置
public void start() {
System.out.println("U盤開始工作");
}
public void stop() {
System.out.println("U盤結束工作");
}
}
class Printer implements USB{ //定義一個印表機裝置
public void start() {
System.out.println("印表機開始工作");
}
public void stop() {
System.out.println("印表機結束工作");
}
}
public class 介面的應用 {
public static void main(String[] args) {
Computer.work(new USBDesk()); //模擬U盤通過USB介面連線電腦
Computer.work(new Printer()); //模擬印表機通過USB介面連線電腦
}
}
程式執行結果:
U盤開始工作
工作中···
U盤結束工作
印表機開始工作
工作中···
印表機結束工作
7、Java面向物件之泛型
認識泛型:
泛型是在JDK1.5 之後新增的新功能。泛型(Generic)。
泛型可以解決資料型別的安全性問題,他的主要原理,是在類宣告的時候通過一個標識表示類中某個屬性的型別或者是某個方法的返回值及引數型別。
格式:
訪問許可權 class 類名稱<泛型,泛型···>{ 屬性 方法 }
物件的建立: 類名稱<具體型別> 物件名稱 = new 類名稱<具體型別>
例如:
package java面向物件;
//表示經緯度,座標x,y
class Point<T>{ //一般用T表示
private T x;
private T y;
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public T getY() {
return y;
}
public void setY(T y) {
this.y = y;
}
}
public class 認識泛型 {
public static void main(String[] args) {
Point p = new Point<String>();
//需要什麼型別的資料,就在尖括號中宣告什麼型別的資料
p.setX("經度為:10");
p.setY("緯度為:20");
System.out.println(p.getX()+" "+p.getY());
}
}
構造方法使用泛型:
構造方法可以為類中的屬性初始化,那麼如果類中的屬性通過泛型指定,而又需要通過該構造方法設定屬性內容的時候,那麼構造方法得的定義與之前並無不同,不需要像宣告類那樣指定泛型。
例如:
package java面向物件;
class Generic<T>{
private T value;
public Generic(T value) {
this.value = value;
}
public void setValue(T value) {
this.value = value;
}
public T getValue() {
return value;
}
}
public class 構造方法中使用泛型 {
public static void main(String[] args) {
//尖括號中的型別可以根據需要任意指定資料型別
Generic<Integer> g = new Generic(10);
System.out.println(g.getValue());
}
}
設定多個泛型:
設定多個泛型直接在< >新增多個泛型就可以了。
例如:
class G<K,T>{
private K key;
private T take;
}
萬用字元:
在泛型<>中填入”?” ,代表什麼型別都可以匹配。
泛型介面:
- 在JDK1.5之後,不僅僅可以宣告泛型類,也可以宣告泛型介面,宣告泛型介面和宣告泛型類的語法類似,也是在介面的名稱後面加上.
- 格式: interface 介面名稱<泛型標識>
例如:
package java面向物件;
interface Interface<T>{
public void say();
}
class Gin<T> implements Interface<T>{
public void say() {
System.out.println("泛型介面");
}
}
public class 泛型介面 {
public static void main(String[] args) {
Gin<String> g = new Gin<String>();
g.say();
}
}
泛型方法:
- 泛型方法中可以定義泛型引數,此時,引數的型別就是傳入資料型別。
- 格式: 訪問許可權 <泛型標識> 泛型標識 方法名稱([泛型標識 引數名稱])
例如:
package java面向物件;
//格式: 訪問許可權 <泛型標識> 泛型標識 方法名稱([泛型標識 引數名稱])
class Gener{
public <T>T tell(T t){
return t;
}
}
public class 泛型方法 {
public static void main(String[] args) {
Gener g = new Gener();
String str = g.tell("hello");
System.out.println(str);
int i = g.tell(10);
System.out.println(i);
}
}
泛型陣列:
在使用泛型方法的時候,也可以傳遞過返回一個泛型陣列。
例如:
package java面向物件;
public class 泛型陣列 {
public static void main(String[] args) {
String arr[] = {"hello","word","nihao"}; //字串型陣列
tell(arr);
Integer arr1[] = {1,2,3,4,5}; //整形陣列
tell(arr1);
}
public static <T>void tell(T arr[]){
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}