java编程基础总结——11.面向对象的三大特征

面向对象的三大特征:
    封装
    继承
    多态


一、封装

1. 面向对象的封装有两层含义:
        |-- 类,属性、方法等这些封装在类中
        |--  为了安全考虑,在开发的过程中,会将属性私有化(private关键字修饰)。
           访问和设置属性:需要提供对应接口完成设置和访问(公开的setter和getter方法)的过程。

package com.openlab.day12;

public class Test01 {
	public static void main(String[] args) {
		Cat cat = new Cat();
		// 设置猫的id
		cat.setId(2);
		System.out.println(cat.getId());
	}
}

class Cat {
	// 首先私有化属性
	private int id;
	private String name;
	private int age;
	
	// 获取id的方法
	public int getId() {
		return this.id;
	}
	
	// 设置id的方法
	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
}

2. JOPO对象(Plain Ordinary Java Object)
    标准的java bean对象
    根据封装来写
    私有化属性
    提供公开的setter和getter方法
    至少两个或者以上的构造方法

package com.openlab.day12;

public class Book {

	private int id;
	private String name;
	private double price;
	private Author author;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	public Author getAuthor() {
		return author;
	}

	public void setAuthor(Author author) {
		this.author = author;
	}

	public Book() {
	}

	public Book(int id, String name, double price, Author author) {
		super();
		this.id = id;
		this.name = name;
		this.price = price;
		this.author = author;
	}

	@Override
	public String toString() {
		return "Book [id=" + id + ", name=" + name + ", price=" + price + ", author=" + author + "]";
	}

}
package com.openlab.day12;

/**
 * 标准的JOPO对象
 *
 *
 */
public class Author {

	private int id;
	private String name;
	private String gender;
	private int age;
	private String intro;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getIntro() {
		return intro;
	}

	public void setIntro(String intro) {
		this.intro = intro;
	}

	public Author() {
	}

	public Author(int id, String name, String gender, int age, String intro) {
		this.id = id;
		this.name = name;
		this.gender = gender;
		this.age = age;
		this.intro = intro;
	}

	public Author(String name, String intro) {
		super();
		this.name = name;
		this.intro = intro;
	}

	@Override
	public String toString() {
		return "Author [id=" + id + ", name=" + name + ", gender=" + gender + ", age=" + age + ", intro=" + intro + "]";
	}
	
}

3. 私有化构造函数:
    |-- 工具类(静态方法或者静态属性)如Math,Arrays。通过类名访问,不需要创建对象。
    |-- 单例模式(一个类只需要一个对象)如任务管理器

饿汉式单例模式:提前准备好了

package com.openlab.day12;

/*public class Singleton {
	
	// 1、私有化构造函数
	private Singleton() {}
	
	// 2、给使用者提供一个创建好的对象
	public static Singleton newInstance() {
		return new singleton();
	}

}*/
//这样写每一次创建一个新对象,还不如将构造函数开放,让自己创建
//单例模式只想有一个对象,则不能每一次调用都创建一个

public class Singleton {
	
	// 饿汉式单例模式
	private static Singleton singleton = new Singleton();
	
	// 1、私有化构造函数
	private Singleton() {}
	
	// 2、给使用者提供一个创建好的对象
	public static Singleton newInstance() {
		return singleton;
	}

}

缺陷:要是一直不用,则白白浪费内存空间(static不管用不用都提前加载内存,直到程序结束,才回收)。由此引出懒汉式单例模式

package com.openlab.day12;

public class Singleton2 {
	
	// 懒汉式单例模式
	private static Singleton2 singleton = null;
	
	// 1、私有化构造函数
	private Singleton2() {}
	
	// 2、给使用者提供一个创建好的对象
	public static Singleton2 newInstance() {
		if (singleton == null) {
			singleton = new Singleton2();
		}
		return singleton;
	}

}

好处:只有访问了,需要时才会创建(访问之后就和饿汉式一样了)

缺陷:代码

if (singleton == null) {
            singleton = new Singleton2();

}

//有问题,多线程中,多个人同时访问第一行。假如第一个线程进了,还没来得及创建,第二个线程进来了,此时就会创建两个对象,出问题。(等学完多线程后,会用dcl来解决)


4. 面向对象的专业术语:
    OO(Oriented Object):面向对象
    OOP(Oriented Object Programming):面向对象的编程
    OOD(Oriented Object Design):面对对象的设计
    OOA(Oriented Object Analysis):面向对象的分析
    OOT(Oriented Object Test):面向对象的测试

二、继承

    在面向对象中,类与类之间可以存在继承关系
    在Java中,也存在继承,java是一种典型的单继承编程语言。

1. java如何实现继承:
    extends    
    父类(超类、基类):
    子类:
注意:private修饰的属性和方法都是无法被子类继承的

    protected修饰的方法,就是用来给子类继承!!!

package com.openlab.day12.inherit;

public class RichMan {
	
	public double money = 100000000;
	protected String company = "google";
	String car = "兰博基尼";
	private String secretary = "秘书";
	
	
	protected void say() {
		System.out.println("好好加油");
	}
	
}
package com.openlab.day12;

import com.openlab.day12.inherit.RichMan;

public class Son extends RichMan {
	
	public static void main(String[] args) {
		// 开始执行创建对象的代码
		Son son = new Son();
		
		System.out.println(son.car);//不报错
	    System.out.println(son.company);//不报错
		System.out.println(son.money);//不报错
//		System.out.println(son.secretary);报错,私有属性
		
    }
}

2. 继承的功能:
    减少代码的重复,提高代码的复用度。(很多类需要同一个方法,将这个方法定义在一个公共的父类中,让其他类继承,从而调用方法)

3. 方法重写(覆盖)
    重写(OverWrite)
    覆盖(OverRide)

    发生在继承中,指的是,子类继承了父类方法后,该方法不能满足子类,
    重写该方法,已达到满足子类使用。

    访问修饰符 返回值类型 名称一致() {
    
    }

注意:访问修饰符的权限可以扩大,但是不能缩小

//父类为protected,子类可以为protected或者public,不能缩小权限

protected void say() {

         System.out.println("请多多关照");
}


4. 注解(annotation):
    JDK5.0提供的新特性,利用反射技术,可以很轻松使用标注方法、属性、类等,
    从而扩展功能。    

@Override    // 覆盖
@Deprecated    // 过时警告
@SuppressWarnings    //压制警告
 

@Override    // 该方法就是重写的方法

protected void say() {

         System.out.println("请多多关照");
}


5. super关键字
    super在java中,是一个指针,类似于this关键字
    this关键字指向创建的每一个对象
    super会自动指向父类

    super();    // 调用父类的无参构造

//子类新增的方法

public void sayHello(){
        super.say();
}


public static void main(String[] args) {
        Son son = new Son();
        son.sayHello;//会输出父类的say方法
}


6. 对象的创建流程:(考虑继承的情况下)
    1、使用java命令将源码(.java)进行编译,生成字节码文件(.class)
    2、javac命令执行字节码文件
    3、将字节码文件加载进虚拟机(JVM),静态方法区开始加载静态资源
    4、JVM从静态方法区读取主函数,并加载进栈(执行栈被创建了出来)
    5、main函数开始执行, 创建对象的代码,如:Son son = new Son();
    6、在堆内存中开辟对象的内存空间,并分配地址
    7、创建成员变量并进行默认初始化
    8、子类构造函数从非静态方法区加载进栈开始执行
    9、第一句先执行父类的构造函数
    10、父类构造函数执行,为子类继承到的成员变量进行初始化(对象内存空间里的父类空间)
    11、父类构造函数弹栈执行完成
    12、子类构造函数继续执行,此时先对成员变量进行显式初始化
    13、再执行子类构造函数的内容,进行针对性初始化
    14、执行完成,子类构造函数弹栈,将对象的内存空间地址赋予相应的引用变量
        
    
方法区:(Method Area)
元数据区:(Metaspace)

三、多态:

    在继承基础上,才有多态
    概念:父类引用指向子类实例

    List list = new List();            // 创建List对象
    List list = new ArrayList();        // 多态

package com.openlab.day13.test;

public class Animal {

	public void say() {
		System.out.println("我是个动物");
	}

}
package com.openlab.day13.test;

public class Cat extends Animal {
	
	public void sayHello() {
		System.out.println("cat类的方法");
	}
	
}
package com.openlab.day13.test;

public class Test {

	public static void main(String[] args) {
		// 创建一个动物类
		//Animal animal = new Animal();
		//animal.say();父类肯定调的是say()方法
		
		// 创建了一个猫类
		//Cat cat = new Cat();
		//cat.sayHello();子类能调到的是sayHello()方法
		//cat.say();子类也能调到say()方法(继承)
		
		// 如果使用多态创建的猫类
		Animal cat2 = new Cat();
		cat2.say();//调用的是父类的方法,访问不到子类自己的方法。输出  我是个动物
        
		
	}
}

多态,父类引用是无法访问到子类自身定义的方法
但是父类引用可以直接操作子类重写的方法

子类重写父类的方法:

package com.openlab.day13.test;

public class Cat extends Animal {
	
	public void sayHello() {
		System.out.println("cat类的方法");
	}
	
	@Override
	public void say() {
		System.out.println("子类的say方法");
	}
}

此时

 Animal cat2 = new Cat();
 cat2.say();//调用的是父类的方法,访问不到子类自己的方法。输出  我是个动物

即 父类引用可以直接操作子类重写的方法

用更高层(父类)代替所有的子类,且能调用到子类方法

案例:

package com.openlab.day13.test02;

public class Master {
	
	// 使用多态,代指所有的宠物类型
	public void cure(Animal pig) {
		if (pig.getHealth() < 60) {
			pig.cure();
		} 
	}

	public static void main(String[] args) {
		QQ qq = new QQ();
		qq.setHealth(30); // qq生病了
		Master master = new Master();
		master.cure(qq);
		
		// Dog 生病了
		Dog dog = new Dog();
		dog.setHealth(10);
		master.cure(dog);
		
	}

}
package com.openlab.day13.test02;

public class Animal {	
	// 100
	private int health;

	public int getHealth() {
		return health;
	}

	public void setHealth(int health) {
		this.health = health;
	}
	
	// 动物自身存在一个治疗自己的方法
	// 该方法,存在的意义就是用来重写,因此函数体的代码就没有意义
	public void cure(Animal pig){

    }
	
}
package com.openlab.day13.test02;

public class QQ extends Animal {
	
	@Override
	public void cure() {
		if (this.getHealth() < 60) {
			System.out.println("给冰块");
			System.out.println("给水,让它玩");
			this.setHealth(100);
		} else {
			System.out.println("琪琪需要和你玩");
		}
	}

}
package com.openlab.day13.test02;

public class Dog extends Animal {

	@Override
	public void cure() {
		if (this.getHealth() < 60) {
			System.out.println("狗狗生病了");
			System.out.println("打针,吃药");
			this.setHealth(100);
		} else {
			System.out.println("狗狗很健康");
		}
	}
}
package com.openlab.day13.test02;

public class Cat extends Animal {
	
	@Override
	public void cure() {
		if (this.getHealth() < 60) {
			System.out.println("打吊针");
			System.out.println("吃罐头");
			this.setHealth(100);
		} else {
			System.out.println("喵喵需要和你玩");
		}
	}

}

你可能感兴趣的:(java)