封裝
將類的部分信息隱藏在類內,通過提供的固定方法訪問。
訪問修飾符
訪問修飾符 | 本類 | 同包 | 字類 | 其他 |
---|---|---|---|---|
private | √ | |||
默認 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
this
this.屬性名 用來區分局部變量和成員變量
private String name;
private int age;
Student(String name , int age){
this.name = name ;
this.age = age;
}
//但是如果寫成name=name,就並沒有把name賦給Student
this.方法名 用來訪問本類的成員方法
this() 訪問本類的構造方法,必須放在第一條語句(如果放在最後,會覆蓋前面的)
內部類
①成員內部類
原文鏈接:https://blog.csdn.net/weixin_42762133/article/details/82890555
//每個內部類都可以獨立的繼承一個接口的實現,無論外部類是否已經繼承了某個接口的實現,對內部類沒有影響。
public class Outer entends ClassA implements FunctionA{
public class Inner extends ClassB implements FunctionB{
}
}
//當內部類屬性名和外部類屬性名相同時,注意怎樣從內部訪問外部類屬性
//當外部類要訪問內部類,則新建方法,在方法裏面new內部類對象,通過對象訪問
/**
* 外部類、成員內部類的定義
*/
public class Outer {
private int outerVariable = 1;
private int commonVariable = 2;
private static int outerStaticVariable = 3;
//省略getter/setter
/**
* 成員方法
*/
public void outerMethod() {
System.out.println("我是外部類的outerMethod方法");
}
/**
* 靜態方法
*/
public static void outerStaticMethod() {
System.out.println("我是外部類的outerStaticMethod靜態方法");
}
/**
* 內部類
*/
public class Inner {
private int commonVariable = 20;
/**
* 構造方法
*/
public Inner() {
}
/**
* 成員方法,訪問外部類信息(屬性、方法)
*/
public void innerShow() {
//當和外部類衝突時,直接引用屬性名,是內部類的成員屬性
System.out.println("內部的commonVariable:" + commonVariable);
//內部類訪問外部屬性
System.out.println("outerVariable:" + outerVariable);
//當和外部類屬性名重疊時,可通過外部類名.this.屬性名
System.out.println("外部的commonVariable:" + Outer.this.commonVariable);
System.out.println("outerStaticVariable:" + outerStaticVariable);
//訪問外部類的方法
outerMethod();
outerStaticMethod();
}
}
/**
* 外部類訪問內部類信息
*/
public void outerShow() {
Inner inner = new Inner();
inner.innerShow();
}
}
//在其他類中,創建外部類對象,通過外部類創造內部類對象
/*
* 其他類使用成員內部類
*/
public class Other {
public static void main(String[] args) {
//外部類對象
Outer outer = new Outer();
//創造內部類對象
Outer.Inner inner = outer.new Inner();
inner.innerShow();
/*
* 可在Outer中定義get方法,獲得Inner對象,那麼使用時,只需outer.getInnerInstance()即可。
* public Inner getInnerInstance(Inner類的構造方法參數){
* return new Inner(參數);
* }
*/
}
}
②靜態內部類
//靜態內部類的方法只能訪問外部類的static關聯的信息。
//訪問內部類的靜態信息,直接外部類.內部類.靜態信息就可以了。
//靜態內部類可以獨立存在,不依賴於其他外圍類。
public class Outer {
static {
System.out.println("Outer的靜態塊被執行了……");
}
public static class Inner {
public void innerShow() {
System.out.println("innerVariable:" + innerVariable);
System.out.println("內部的commonVariable:" + commonVariable);
System.out.println("outerStaticVariable:"+outerStaticVariable);
outerStaticMethod();
}
public static void innerStaticShow() {
//被調用時會先加載Outer類
outerStaticMethod();
System.out.println("outerStaticVariable"+outerStaticVariable);
}
}
}
③局部內部類
//類前不能有訪問修飾符。
//僅在方法內使用。
//可以直接訪問方法內的局部變量和參數但是不能更改。
//可以隨意的訪問外部類的任何信息。
public class Outer{
private int outa = 1;
public void outerMethod(){
System.out.println("我是外部類的outerMethod方法")
}
public void outerCreatMethod(int value) {
class Inner{
private int innerVariable = 10;
private int commonVariable = 20;
/**
* 局部內部類方法
*/
public void innerShow() {
System.out.println("innerVariable:" + innerVariable);
//調用外部類的信息
System.out.println("outerVariable:" + outerVariable);
System.out.println("內部的commonVariable:" + commonVariable);
System.out.println("外部的commonVariable:" + Outer.this.commonVariable);
System.out.println("outerStaticVariable:" + outerStaticVariable);
outerMethod();
outerStaticMethod();
}
}
}
//入口
public static void main(String[] args) {
Outer outer = new Outer();
outer.outerCreatMethod(100);
}
}
④匿名內部類
/**
* 定義接口
* 接口中方法默認爲public
*/
public interface IAnimal{
void speak();
}
/**
* 外部內、內部類
*/
public class Outer {
public static IAnimal getInnerInstance(String speak){
return new IAnimal(){
@Override
public void speak(){
System.out.println(speak);
}};
//注意上一行的分號必須有
}
public static void main(String[] args){
//調用的speak()是重寫後的speak方法。
Outer.getInnerInstance("小狗汪汪汪!").speak();
}
}
繼承
特性:
- 子類擁有父類非private的屬性、方法
- 子類可以對父類擴展
- 子類可用自己的方式實現父類的方法
- Java可以多重繼承,但是是單繼承
- 提高了類之間的耦合性
關鍵字
- extends
- implements
//可以間接實現多繼承的特性
public interface A{}
public interface B{}
public class C implements A,B{}
- super與this
this.function();//調用自己的方法
super.function();//調用父類的方法
- final
//可以把類定義爲不能繼承的,即最終類;或者用於修飾方法,但是該方法不能被子類重寫
final class 類名{}
構造器
原文鏈接:https://blog.csdn.net/li_jeremy/article/details/79294699
- 創建構造器的規則
①構造函數名和類名相同
②構造函數沒有顯式返回值 - 構造函數類型
//無參數
//顯示默認值的默認構造函數
class Student3 {
int id;
String name;
void display() {
System.out.println(id + " " + name);
}
public static void main(String args[]) {
Student3 s1 = new Student3();
Student3 s2 = new Student3();
s1.display();
s2.display();
}
}
//輸出結果有值爲0 null ,編譯器自動提供默認構造函數,它爲id和name分別提供了0和null。
//有參數
class Student4 {
int id;
String name;
Student4(int i, String n) {
id = i;
name = n;
}
void display() {
System.out.println(id + " " + name);
}
public static void main(String args[]) {
Student4 s1 = new Student4(111, "Karan");
Student4 s2 = new Student4(222, "Aryan");
s1.display();
s2.display();
}
}
- 構造函數重載
Student5(int i, String n) {
id = i;
name = n;
}
Student5(int i, String n, int a) { //通過參數的不同告知編譯器此處用到了構造函數的重載
id = i;
name = n;
age = a;
}
- 拷貝構造函數
//通過構造函數
Student6(int i, String n) {
id = i;
name = n;
}
Student6(Student6 s) { //參數傳入的是類對象
id = s.id;
name = s.name;
}
public static void main(String args[]) {
Student6 s1 = new Student6(111, "Karan");
Student6 s2 = new Student6(s1); //將上面的s1傳入
}
//將對象值分配給另一個對象
Student7(int i, String n) {
id = i;
name = n;
}
Student7() {}
public static void main(String args[]) {
Student7 s1 = new Student7(111, "Karan");
Student7 s2 = new Student7();
s2.id = s1.id; //直接賦值
s2.name = s1.name;
}
Object類
Object類是所有類的父類,其中的方法適合所有子類
- toString()
- equals()
多態
原文鏈接:https://www.runoob.com/java/java-polymorphism.html
優點
- 消除類型之間的耦合關係
- 可替換性
- 可擴充性
- 接口性
- 靈活性
- 簡化性
三個必要條件
- 繼承
- 重寫
- 父類引用指向子類對象
//使程序有良好的擴展,並可以對所有類的對象進行通用處理
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 對象調用 show 方法
show(new Dog()); // 以 Dog 對象調用 show 方法
Animal a = new Cat(); // 向上轉型
a.eat(); // 調用的是 Cat 的 eat
Cat c = (Cat)a; // 向下轉型
c.work(); // 調用的是 Cat 的 work
}
public static void show(Animal a) {
a.eat();
// 類型判斷
if (a instanceof Cat) { // 貓做的事情
Cat c = (Cat)a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
}
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃魚");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨頭");
}
public void work() {
System.out.println("看家");
}
}
- 重寫
//當子類對象調用重寫的方法時,調用的是子類的方法,而不是父類中被重寫的方法
//若要調用父類中被重寫的方法,必須使用關鍵字super
多態的實現方式
重寫
原文鏈接:https://www.runoob.com/java/java-override-overload.html
//必須是重寫父類已有的方法
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 b = new Dog(); // Dog 對象
a.move();// 執行 Animal 類的方法
b.move();//執行 Dog 類的方法
b.bark(); /////////////////////////bark在父類裏面並沒有,報錯
}
}
重寫規則:
- 參數列表必須完全與被重寫方法的相同
- 返回類型與被重寫方法的返回類型可以不相同,但是必須是父類返回值的派生類
- 訪問權限不能比父類中被重寫的方法的訪問權限更低
- 聲明爲 final 的方法不能被重寫
- 聲明爲 static 的方法不能被重寫,但是能夠被再次聲明
- 構造方法不能被重寫
- 如果不能繼承一個方法,則不能重寫這個方法
重載
被重載的方法必須改變參數列表(參數個數或類型不一樣)
public String test(int a,String s){
System.out.println("test3");
return "returntest3";
}
public String test(String s,int a){
System.out.println("test4");
return "returntest4";
}
接口
除非實現接口的是抽象方法,否則要實現接口中的所有方法
抽象類和抽象方法
抽象類:一個類中沒有包含足夠的信息來描繪一個具體的對象
抽象方法:方法的具體實現又子類確定