Java面向對象編程(筆記)
面向對象編程(Object-Oriented Programming.OOP)
Java的核心思想就是面向對象編程
面向對象編程的本質是:以類的方式組織代碼。以對象的組織封裝數據
面向對象三大特征:
- 封裝
- 繼承
- 多態
從認識論角度考慮是先有對象后有類。對象是具體的事物。類是抽象的,是對對象的抽象
從代碼運行的角度考慮是先有類后有對象。類是對象的模板
類與對象的關系
類是一種抽象的數據類型,它是對某一類事物整體描述/定義,但是并不能代表某一個具體的事物
對象是抽象概念的具體實例
- 能夠體現出特點,展現出功能的是具體的實例,而不是一個抽象的概念
使用new關鍵字來創建對象
使用new關鍵字創建的時候,除了分配內存空間之外,還會給創建好的對象進行默認的初始化以及對類中構造器的調用
類中的構造器也稱為構造方法,是在進行創建對象的時候必須要調用的。并且構造器有以下兩個特點:
- 必須和類的名字相同
- 必須沒有返回類型,也不能寫void
//學生類
//類中只可能存在屬性和方法
public class Student {
//屬性:字段
String name;
int age;
//方法:行為
public void study(){
//this指的是本類的
System.out.println(this.name+"在學習");
}
}
//一個項目應該只有一個main方法
//一個類中最多只能有一個main方法
public class Application {
public static void main(String[] args) {
//類是抽象的,可以通過new實例化
//類實例化會返回一個對象,對象就是這個被new類的具體實例
Student xiaoming = new Student();
Student xiaohong = new Student();
xiaoming.name = "小明";
xiaoming.age = 13;
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
xiaohong.name = "小紅";
xiaohong.age = 13;
System.out.println(xiaohong.name);
System.out.println(xiaohong.age);
//類是抽象的,可以通過實例去具體實現
//上邊的代碼中,new的是同一個類卻得到兩個具體的實例
}
}
小結
- 類與對象:類是一個模板(抽象),對象是一個具體的實例
- 對象的應用:引用類型(除八大基本類型外的),對象是通過引用來操作的
- 屬性:字段,成員變量
- 對象的創建和使用:必須使用new關鍵字創建對象,構造器;對象的屬性;對象的方法
- 類:靜態的屬性 屬性;動態的行為 方法
封裝
- 封裝使程序更加安全更加方便,也可以保護數據
- 隱藏代碼的實現細節
- 統一接口,提高了代碼的規范
- 系統的可維護性增加了
我們程序設計要追求“高內聚,低耦合”。高內聚就是類的內部數據操作細節自己完成,不允許外部干涉;低耦合就是僅暴露少量的方法給外部使用
封裝: (隱藏的數據) 通常,應禁止直接訪問一個對象中數據的實際表示,而應通過操作接口來訪問,這稱之為信息隱藏
public class Student {
//封裝主要是針對屬性
//private私有的,只有本類可以訪問到
private String name;
private int id;
private char sex;
private int age;
public int getAge() {
return age;
}
//封裝可以限制數據,比如年齡不可能為負數,可以在set方法里設置范圍
public void setAge(int age) {
if (age>100 || age<0){
System.out.println("還是人嘛?");
}else {
this.age = age;
}
}
//通過get,set方法別的類也可以訪問到這些屬性
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.setName("張三"); //通過set方法設置值
String name = student.getName(); //通過get方法獲取值
System.out.println(name); //張三
student.setAge(100);
int age = student.getAge();
System.out.println(age);
}
}
繼承
- 繼承的本質是對某一批類的抽象,從而實現對現實世界更好的建模
- extends的意思是“擴展”。子類是父類的擴展。
- Java中只有單繼承,沒有多繼承
- 繼承是類和類之間的一種關系。除此之外,類和類之間的關系還有依賴、組合、聚合等
- 繼承關系的兩個類,一個為子類(派生類),一個為父類(基類)。子類繼承父類,使用關鍵字extends來表示
- 子類和父類之間,從意義上講應該具有“is a”的關系
//父類
//在Java中所有的類,都默認直接或間接繼承object
public class Person {
public int money = 10_0000_0000;
public void say(){
System.out.println("說話");
}
}
//子類
//子類繼承了父類,就會擁有父類的全部方法。
// 前提是父類方法的修飾符是public,如果是privte私有的子類就不能直接使用
public class Student extends Person {
}
//子類
public class Teacher extends Person {
}
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.say();//子類可以調用父類的方法
System.out.println(student.money);//1000000000
}
}
Super
- super調用父類的構造方法,必須在構造方法的第一個
- super必須只能出現在子類的方法或者構造方法中
- super和this不能同時調用構造方法
super和this
代表對象不同:
- this:本身調用這個對象
- super:代表父類的應用
前提:
- this:沒有繼承也可以使用
- super:只能在繼承條件下才可以使用
構造方法:
- this:本類的構造
- super:父類的構造
public class Person {
//父類私有的屬性和方法子類可以繼承但不能被訪問
public String name = "zhangsan";
public void print(){
System.out.println("Person");
}
public Person() {
System.out.println("Person無參執行了");
}
}
public class Student extends Person {
private String name = "lisi";
public void print(){
System.out.println("Student");
}
//在子類的內部調用父類的方法和屬性是通過super來實現的
public void test1(){
print(); //Student
this.print(); //Student
super.print(); //Person
}
public void test(String name){
System.out.println(name); //輸出方法里邊的name
System.out.println(this.name);//輸出本類的name
System.out.println(super.name);//輸出父類的name
}
public Student() {
//隱藏代碼:super調用了父類的構造器,而且必須要在子類構造器的第一行
super();//this和super只能有一個而且必須在第一行
System.out.println("Student無參方法執行了");
}
}
public class Appliction {
public static void main(String[] args) {
Student student = new Student();
System.out.println("=====================");
student.test("王五");
System.out.println("=======================");
student.test1();
}
}
方法的重寫
重寫發生在繼承關系中,子類重寫父類的方法
重寫都是方法的重寫,和屬性無關
重寫和靜態的方法無關,只能重寫非靜態的方法
父類的方法修飾符只要不是private都可以重寫
子類的方法和父類的方法必須要一致,方法體不同
- 方法名必須相同
- 參數列表必須相同
- 修飾符的范圍可以擴大,但不能縮小
- public>protected>default(默認的)>private
- 拋出的異常范圍,可以被縮小,但不能擴大
為什么要重寫
- 父類的功能,子類不一定需要,或者不一定滿足
public class B {
public static void test(){
System.out.println("B-test");
}
public void test1(){
System.out.println("B類非靜態的");
}
}
public class A extends B {
public static void test(){
System.out.println("A-test");
}
@Override//重寫
public void test1(){
System.out.println("A類非靜態的");
}
}
/*靜態的方法可以被繼承,但是不能重寫。
如果父類中有一個靜態的方法,子類也有一個與其方法名,
參數類型,參數個數都一樣的方法,并且也有static關鍵字修飾,
那么該子類的方法會把原來繼承過來的父類的方法隱藏,而不是重寫。
通俗的講就是父類的方法和子類的方法是兩個沒有關系的方法,
具體調用哪一個方法是看是哪個對象的引用;
這種父子類方法不在存在多態的性質。*/
public class Appliction {
public static void main(String[] args) {
//方法的調用只和左邊,定義的數據類型有關
A a = new A();
a.test();//A-test
//父類的引用指向了子類
B b = new A();
b.test();//B-test
//方法重寫了
a.test1();//A類非靜態的
b.test1();//A類非靜態的
}
}
多態
通過多態可以使代碼的可擴展性更強
一個對象的實際類型是確定的,但可以指向對象的引用的類型有很多
多態是方法的多態,屬性沒有多態
多態存在的條件
- 有繼承關系
- 子類重寫父類方法
- 父類引用指向子類對象
不能被重寫的方法
- static方法屬于類,它不屬于實例
- final方法屬于常量,不能被修改
- private方法不能被重寫
public class Person {
public void run(){
System.out.println("run");
}
}
public class Student extends Person {
@Override
public void run(){
System.out.println("son");
}
public void Study(){
System.out.println("Study");
}
}
public class Application {
public static void main(String[] args) {
//一個對象的實際類型是確認的
//父類的引用指向子類
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();//object是所有類的祖宗類
//對象能執行那些方法,主要看左邊的類型
s1.run(); //子類能調用的方法都是自己的或者繼承父類的
s2.run(); //子類重寫了父類的方法執行子類的方法
//父類可以指向子類,但是不能調用子類獨有的方法。如果要掉用則必須強轉
((Student) s2).Study();
}
}
instanceof和類型轉換
instanceof主要用來判斷兩個類是否有關系
子類轉父類:向上轉型,直接專門丟失子類中原本可以直接調用的特有方法
父類轉子類:向下轉型,會丟失父類被子類重寫的方法
類型轉換能方便方法的調用,減少重復的代碼,使代碼更加簡潔
public class Person {
public void run(){
System.out.println("run");
}
}
public class Student extends Person {
public void go(){
System.out.println("go");
}
}
public class Teacher extends Person {
}
public class Appliication {
public static void main(String[] args) {
//類型之間的轉換:
Person student1 = new Student();
((Student) student1).go();
System.out.println("==========");
//System.out.println(x instanceof y);
//能不能編譯通過主要看xy有沒有父子關系
//Object > Person > Teacher
//Object > Person > Student
//Object > String
Object object = new Student();
//studnet跟teacher和string無關
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);// true
System.out.println(object instanceof Object);// true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof String);//false
System.out.println("===============================");
Person person = new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);// true
System.out.println(person instanceof Object);// true
System.out.println(person instanceof Teacher);//false
//System.out.println(person instanceof String);編譯報錯
//person和String沒有一點關系,他們是同級的
System.out.println("===============================");
Student student = new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Person);// true
System.out.println(student instanceof Object);// true
//System.out.println(student instanceof Teacher);編譯報錯
}
}
static關鍵字
static用在方法上是靜態方法,用在屬性上是靜態屬性
靜態變量對于類,所有對象(實例)所共享。可以直接使用類去調用
public class Student {
private static int age;//靜態的屬性
private double score;//非靜態的屬性
public void run(){
}//非靜態的方法
public static void go(){}//靜態的方法
public static void main(String[] args) {
//非靜態方法可以調用靜態方法,
// 靜態方法可以調用靜態方法但不能調用非靜態的方法
new Student().run();
go();
Student s1 = new Student();
//靜態的屬性可以通過類直接調用
System.out.println(Student.age);
System.out.println(s1.age);
System.out.println(s1.score);
}
}
public class Application {
{
//代碼塊(匿名代碼塊)
System.out.println("匿名代碼塊");
}
static {
//靜態代碼塊:跟類一塊加載,永久只執行一次
System.out.println("靜態代碼塊");
}
public Application() {
System.out.println("構造方法");
}
public static void main(String[] args) {
Application application1 = new Application();
System.out.println("===============");
Application application2 = new Application();
/*
靜態代碼塊
匿名代碼塊
構造方法
===============
匿名代碼塊
構造方法
*/
}
}
抽象類
abstract修飾符可以用來修飾方法也可以修飾類,如果修飾方法,那么該方法就是抽象方法,如果修飾類,那么該類就是抽象類
抽象類中可以沒有抽象方法,但是有抽象方法的類一定要聲明為抽象類。
抽象類不能使用new關鍵字來創建對象,它是用來讓子類繼承的
抽象方法,只有方法的聲明,沒有方法的實現,它是用來讓子類實現的
子類繼承抽象類,那么就必須要實現抽象類沒有實現的抽象方法,缶則該子類也要聲明為抽象類
//抽象類
public abstract class Action {
//抽象方法,只有方法名字,沒有方法的實現
public abstract void run();
public void go(){
//抽象類中可以寫普通的方法
System.out.println("go");
}
}
//抽象類的所有方法必須要有子類實現,除非子類也是抽象方法
public class A extends Action{
//子類必須要重寫父類的抽象方法
@Override
public void run() {
}
}
接口
聲明類的關鍵字是class,聲明接口的關鍵字是interface
普通類: 只有具體實現
抽象類: 具體實現和規范(抽象方法)都有
接口: 只有規范
- 接口就是規范,定義的是一組規則
- 接口的本質是契約,就像法律一樣。制定好后所有人都要遵守
- 面向對象的精髓,是對對象的抽象,最能體現這一點就是接口。設計模式所研究的,實際上就是如何合理的去抽象
- 接口不能被實例化,接口中沒有構造方法
public interface Test {
void run();
}
//接口也可以繼承接口。
// 子類接口被實現后,實現類要重寫父類接口和子類接口的所有方法
public interface UserService extends Test{
//接口中定義的屬性都是常量
int age = 18;
//接口中不能寫方法的實現
//接口中所有定義的方法都是抽象方法
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
//接口可以多實現
public class UserServiceImpl implements UserService,Test{
//類可以實現接口,實現接口的類必須要重寫接口的所有方法
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void run() {
}
}
浙公網安備 33010602011771號