面向对象之四

mac2022-06-30  23

一、多态

1、多态理解

简单理解:一种类型多种形态

 

如上图:animal a = new Person()中编译时类型与运行时类型不一致,此时,我们就说产生了多态。

注意,编译时类型必须是运行时类型的父类或者祖先类

2、理论重点

因为字段、静态方法不能被覆写,所以当子类和父类出现相同的字段或者静态方法时,在多态情况下,我们就看是谁的对象在调用,则就使用谁的值。怎么看是谁的对象?看这个对象保存在什么类型的变量中那就为谁的对象

3、多态方法的调用以及参数的传递

实例代码:

class Test2{

public static void main(String[] args){

Person p = new Person();

//方式一

p.feedTuGou(new TuGou());

p.feedZangAo(new ZangAo());

p.feedSaMoYe(new SaMoYe());

//方式二

p.feedDog(new SaMoYe());

}

}

class Person{

//方式一

void feedTuGou(TuGou z){

z.eat();

}

void feedZangAo(ZangAo z){

z.eat();

}

void feedSaMoYe(SaMoYe z){

z.eat();

}

//方式二   运用多态    多态的好处:屏蔽各子类之间的实现差异,少写代码

void feedDog(Dog dog){  //Dog dog = new SaMoYe();

dog.eat();

//引用数据类型小转大,自动隐式转;大转小,强制转

}

}

class Dog{

void eat(){

System.out.println("吃狗粮。。。");

}

}

class TuGou extends Dog{

@Override

void eat(){

System.out.println("吃五谷杂粮。。。");

}

}

class ZangAo extends Dog{

@Override

void eat(){

System.out.println("吃肉食。。。");

}

}

class SaMoYe extends Dog{

@Override

void eat(){

System.out.println("吃进口狗粮。。。");

}

}

二、引用数据类型转换

1、引用数据类型转换

小转大自动隐式转;大转小,必须强制转。

Animal a = new Person();    这是自动隐式转

Person p = (Person)a;        这是强制转

2、数据类型转换总结

基本数据类型、引用数据类型小转大,自动隐式转;大转小,必须强制转。

三、Final(是修饰符,但不是权限修饰符)

1、那些能被final修饰?

能被final修饰得有:类、字段、方法、代码块、局部变量(唯一能修饰的)

不能被final修饰的有:构造方法

2、final修饰后的特点

final修饰的类:属于太监类,不能被继承;

final修饰的字段:必须要有初始值,如果没有初始值,必须要有构造方法为其传值,一旦传值,不可改变;

final修饰的方法:能被继承,不能被覆写;

final修饰的局部变量:可以没有初始值,一旦传值,不可改变。

final一般修饰到字段上,被final所修饰的字段值是不能更改的

注意:被public static final所修饰的变量,叫做全局常量

四、单例模式

1、饿汉模式:一上来就要获得对象

示例代码:

class SingleInstance7{

public static void main(String[] args){

Person a = Person.getInstance();

Person b = Person.getInstance();

System.out.println(a==b);

}

}

/**

饿汉模式:一上来就要获得对象;饿汉模式的思路:产生实例的原因是外面不断的new,调用内部的构造方法,因此,我们将构造方法私有化,这个时候就只有在内部调用构造方法了,因此在内部new一个对象保存在instance里面,同时又要避免外面通过调用字段更改对象的值,所有将字段私有化,此时就需要放出一个公共的getter方法,让外面来获得这个对象的变量名,也就只能操作这个变量名。

饿汉模式存在的问题:占用内存。

static修饰的字段、代码块在使用该类的时候就会马上执行,如果我执行的是一个普通的方法,并不是获得

对象的方法,他也会立即创建对象。

*/

class Person{

private Person(){

}

private static Person instance = new Person();

public static Person getInstance(){

return instance;

}

}

2、懒汉模式:在需要的时候才来创建一个实例

示例代码:

class SingleInstaace8{

public static void main(String[] args){

System.out.println("come on 梓沐!");

}

}

/**

懒汉模式:在需要的时候才来创建一个实例;

懒汉模式存在的问题:线程安全问题,解决办法:加锁

*/

class Person{

private Person(){

}

private static Person instance;

public static Person getInstance(){

if(instace == null){

instance = new Person();

}

return instance

}

}

五、代码块(后两种代码块的运行方式都是new一个对象的时候运行)

1.普通代码块(了解):存在方法内部的代码块

2.构造代码块(了解):直接申明在类中的代码块,当编译完成之后,它会把构造代码块的内容放到构造方法第一句

3.静态代码块(重点):使用该类的时候,就会马上执行

static修饰的字段或者代码块,在使用该类的时候马上执行,并且只会执行1次

4、代码块执行顺序理解

示例代码:

class TestStatic12{

/**执行顺序: 静态代码块和静态成员 首先先执行,如果父类有,先执行父类的静态代码块和静态成员,再执行子类的静态代码块和静态代码块,再执行父类构造代码块,父类的构造方法,子类的构造代码块,子类的构造方法

   执行顺序:类的静态代码块/类的静态变量----》子类的静态代码块/子类的静态变量----》父类的构造代码块/父类的构造方法--->子类的构造代码块/子类的 构造方法

在类中,static所修饰的字段和static修饰的代码块,谁在前面,谁就先执行

*/

public static void main(String[] args){

new B();//其实你在new子类的时候,它会先创建父类对象,然后在父类对象的基础上添加子类成员,最终成为子类对象

}

}

class A{

static int a = 3;

static{

System.out.println("A静态代码块"+a);

}

{

System.out.println("A构造代码块");

}

A(){

System.out.println("A无参数的构造方法");

}

}

class B extends A{

static{

System.out.println("B静态代码块");

}

{

System.out.println("B构造代码块");

}

B(){

System.out.println("B无参数的构造方法");

}

}

5static修饰的静态代码块、静态变量生命周期理解

static修饰的字段和static修饰的代码块生命周期:

1.类被加载的时候,就存在jvm

2.类被卸载的时候,该生命周期就会结束(程序结束,关闭jvm)

六、组合关系

1 组合是(has-a)关系,而继承则是(is-a)关系;

2 组合关系在运行期决定,而继承关系在编译期就已经决定了。

3组合是在组合类和被包含类之间的一种松耦合关系,而继承则是父类和子类之间的一种紧耦合关系。

4当选择使用组合关系时,在组合类中包含了外部类的对象,组合类可以调用外部类必须的方法,而使用继承关系时,父类的所有方法和变量都被子类无条件继承,子类不能选择。

5、组合关系理解的示例代码

class TestGroup6{

public static void main(String[] args){

Card card = new Card("110");

CellPhone c = new CellPhone("小米8",card);

c.show();

}

}

//组合关系的关键步骤理解:其实简单理解就是通过将要组合到另一个类里面的类型以字段的形式出现在这个类里面

class CellPhone{

private String brand;

private Card card; //这是一个字段,以后就是通过这种形式来组合另外一个类

CellPhone(){

}

CellPhone(String brand,Card card){

this.brand = brand;

this.card = card;

}

public void setBrand(String brand){

this.brand = brand;

}

public String getBrand(){

return brand;

}

public void setCard(Card card){

this.card = card;

}

public Card getCard(){

return card;

}

public void show(){

System.out.println("您的手机品牌为"+brand + "   您的手机号码为" + card.getNum()); //得到卡的号码

}

 

}

class Card{

private String num; //手机号码

Card(){

}

Card(String num){

this.num = num;

}

public void setNum(String num){

this.num = num;

}

public String getNum(){

return num;

}

}

转载于:https://www.cnblogs.com/limengkun/p/10617289.html

最新回复(0)