Java封装与继承

Java封装与继承

1、垃圾回收机制(Garbage Collection)

JAVA的内存管理实际上指的就是对象的管理,其中包括对象空间的分配和释放。

对象空间的分配:

使用new关键字创建对象即可

对象空间的释放:

将引用数据类型变量赋值null即可。垃圾回收器将负责回收所有“不可达”对象的内存空间。

System.gc() 通知的作用,通知垃圾回收机制回收垃圾,是否回收,什么时候回收无法控制

finalize() 回收垃圾会先调用对象的这个方法

2、package包和导包

在java中我们通过package实现对类的管理,我们将相同功能的类放到一个包中,并且日常项目的分工也是以包作为边界。

注意:同一个包中,不允许有相同的类名。

【示例】包的命名举例

com.object
com.object.demo

注意:com.object和com.object.demo,这两个包没有包含关系,是两个完全独立的包。只是逻辑上看起来后者是前者的一部分。

【示例】包的声明举例

package com.object; // 包的声明,必须在有效代码的第一行(注释不算)
// 以下是业务逻辑所需要的代码
class Person {}

注意:当前包中的类可以直接使用!

2.1 java常用包

常用包说明
java.lang包含一些Java语言的核心类,如String、Math、System等。
java.awt包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。
java.net包含执行与网络相关的操作的类。
java.io包含能提供多种输入/输出功能的类。
java.util包含一些实用工具类,如定义系统特性、使用与日期日历相关的函数。

2.2import导入类

导包的格式:import 包名.类名;

import 导包代码书写的位置:在声明包 package 后,定义所有类 class 前。

【示例】import的使用举例(一)

package com.object; 
// 导入位置:在声明包package后,定义所有类class前。
import java.util.Date; // 导入日期类
public class Test {
	public static void main(String[] args) {
		// 使用Date类
		Date date = new Date();
	}
} 

【示例】import的使用举例(二)

package com.object; 
// 导入位置:在声明包 package后,定义所有类 class前。
import java.util.*; // 导入该包下所有的类。会降低编译速度,但不会降低运行速度。
class Test {
	public static void main(String[] args) {
		// 使用java.util包下的类
		Date date = new Date();
		Scanner s = new Scanner(System.in);
	}
}

注意:如果导入两个同名的类,只能用包名+类名来显示调用相关类。

3、封装(encapsulation)

面向对象编程有三大特性:封装、继承、多态。

封装是指隐藏对象的属性和实现细节,仅对外提供公共的访问方式

封装的优点

  1. 提高代码的安全性。
  2. 提高代码的复用性。

封装原则:

  1. 将不需要对外提供的内容都隐藏起来。
  2. 把属性都隐藏,提供公共方法对其访问。

3.1访问控制符

修饰符同一个类同一个包子类所有类
private*
default**
protected***
public****

private:表示私有的,作用范围是当前类(类可见性)。

default:表示没有修饰符修饰,作用范围是当前类+当前包(包可见型)。

protected:表示受保护的,作用范围是当前类+当前包+其它包中的子类(子类可见性)。

public:表示公开的,作用范围是是当前类+当前包+其它包(项目可见性)。

注意事项:

  1. 类中的属性和方法访问权限共有四种:private、default、protected和public。
  2. 类的访问权限只有两种:public和default。
  3. 访问权限控制符不能修饰局部变量。

3.2成员变量封装

我们在操作属性时,通常会对数据进行封装,这样就可以增加了数据访问限制,增加了程序可维护性。

实现方式:提供相应的get/set方法来访问相关属性,使用set方法实现对属性的赋值操作,使用get方法实现对属性的取值操作。

关于使用权限修饰符补充:

  1. 属性一般使用private访问权限。
  2. 提供访问相关属性get/set方法通常是public修饰的,以方便对属性的赋值与读取操作。
  3. 一些只用于本类的辅助性方法可以用private修饰,希望其他类调用的方法用public修饰。

【示例】JavaBean的封装实例

class Person {
	// 成员方法,一般使用private修饰
	private String name;
	private int age;
	private boolean marry; // 是否已婚
	// set和get方法,一般使用public修饰
	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;
	}
	// boolean类型的成员变量,get方法是is开头的。
	public boolean isMarry () {
		return marry;
	}
	public void setMarry(boolean marry) {
		this.marry = marry;
	}
}
public class EncapsulationDemo {
	public static void main(String[] args) {
		Person person = new Person();
		// 赋值操作
		// person.name = "小明"; // 编译失败
		person.setName("小明");
		person.setAge(18);
		person.setMarry(true);
		// 取值操作
		// String name = person.name; // 编译失败
		String name = person.getName();
		int age = person.getAge();
		boolean isMarry = person.isMarry);
		System.out.println("name:"+name+" age:"+age+" isMarry:"+isMarry);
	}
}

JavaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean,类必须是具体的和公共的,并且具有无参构造器。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性,并提供set和get方法操作成员成员变量。

【示例】可见性封装的使用案例

class Person {
	// 成员方法
	private String name;
	private int age;
	// 构造方法
	public Person() {}
	public Person(String name, int age) {
		this.name = name;
		// 调用set方法来给年龄赋值
		setAge(age);
	}
	// set和get方法
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	// 新增需求:获取年龄的时候要求返回虚岁
	public int getAge() {
		return age + 1;
	}
	// 设置年龄的时候是实岁
	public void setAge(int age) {
		// 在赋值之前先判断年龄是否合法
		if (age > 130 || age < 0) {
			this.age = 0; // 不合法赋默认值0
		} else {
			this.age = age; // 合法才能赋值给属性
		}
	}
	// 成员方法
	void show() { 
		// 输出:name: 小明 age: 0,思考:为什么会这样???
		System.out.println("name: " + name + " age: " + age);
	}
}
public class EncapsulationDemo {
	public static void main(String[] args) {
		Person person = new Person();
		// 赋值操作
		person.setName("小明");
		person.setAge(150);
		// 取值操作
		String name = person.getName();
		int age = person.getAge();
		// 调用成员方法
		person.show();
		// 输出:name:小明 age:1,思考:为什么会这样???
		System.out.println("name:" + name + " age:" + age);
	}
}

4、继承(inheritance)

继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。

在Java之中,如果要实现继承的关系,可以使用如下的语法:

class 父类 {
}
class 子类 extends 父类 {
}

子类又被称为派生类,父类又被称为超类(Super Class)。

【示例】使用extends实现继承

// 父类:Person类
class Person {
	// 成员变量
	private String name;
	// set和get方法
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	// 成员方法
	public void eat() {
		System.out.println("eat...");
	}
}
// 子类,Teacher类
public class Teacher extends Person {
	// 成员变量
	private String title; // 职称
	// set和get方法
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	// 成员方法
	public void teaching() {
		System.out.println("授课...");
	}
}
// 测试类
public class InheritanceDemo {
	public static void main(String[] args) {
		Teacher t = new Teacher();
		t.setName("雨梦"); // 父类属性
		t.setTitle("JavaSE"); // 子类属性
		t.eat(); // 父类方法
		t.teaching(); // 子类方法
		System.out.println("name:"+t.getName()+" age:"+t.getAge());
	}
}

4.1继承的使用要点

继承的好处

  1. 继承的出现提高了代码的复用性,提高软件开发效率。
  2. 继承的出现让类与类之间产生了关系,提供了多态的前提。

继承的注意点

  1. java 只支持单继承,不允许多继承,也就是说一个类只能有一个直接父类。
  2. java 支持多层(重)继承,即一个类的父类可以再去继承另外的父类(继承体系)。
  3. 如果定义一个类时,没有使用extends,则它的父类默认是:java.lang.Object。

5、方法的重写(override)

当父类的方法不能满足子类的需求时,我们可以在子类中重写父类的方法,重写也称为复写。

方法重写需要符合以下三个要点:

  1. == :方法名、形参列表必须相同。

  2. = :访问权限,子类大于等于父类。

    父类的私有方法不能被重写,static修饰的方法不能被重写。

  3. <= :返回值类型和异常类型,子类小于等于父类。

【示例】方法重写案例

// 父类
class Parent {
	public void show(){
		System.out.println("父类中的 show方法执行");
	}
}
// 子类
class Child extends Parent {
	// 子类重写父类的show方法
	public void show(){
		System.out.println("子类中的 show方法执行");
	}
}
public class ExtendsMethodDemo {
	public static void main(String[] args) {
		Child p = new Child();
		p.show(); // 执行的是子类的show方法
	}
}

注意:如果子类重写了父类的方法,通过子类对象调用该方法时,调用的方法就是被覆写过的方法!

如果子类方法需要使用父类方法的功能,可使用super关键字来调用父类方法,该关键字引用了当前对象的父类对象。这样,即沿袭了父类的功能,又定义了子类特有的功能 (super关键字的使用和this非常相似)。

6、super关键字

super可以理解为直接父类对象的引用,或者说super指向子类对象的父类对象存储空间。我们可以通过super来访问父类中被子类覆盖的方法或属性,super的使用和this关键字非常的相似。

【示例】super关键字使用

class Parent {
	String name = "父类";
	public void study() {
		System.out.println("父类中的study方法");
	}
}
class Child extends Parent {
	public void show() {
		// 调用父类的成员方法
		super.study();
		// 调用父类的成员变量
		System.out.println("name:" + super.name);
	}
}
public class SuperDemo extends Parent {
	public static void main(String[] args) {
		new Child().show();
	}
}

6.1super调用父类构造方法

子类继承父类,子类的构造方法必须调用父类的构造方法,如果子类的构造方法中没有显示的调用父类的构造方法,则系统默认调用父类的无参数构造方法。

【示例】默认调用父类的无参数构造方法

class Parent {
	public Parent() {
		System.out.println("parent 构造方法");
	}
}
class Child extends Parent {
	public Child() {
		// 如我们没有显示的使用super(),那么会默认调用父类的无参构造方法
		System.out.println("Child 构造方法");
	}
}
public class SuperDemo {
	public static void main(String[] args) {
		// 创建子类对象,父子类构造方法都执行!!!!
		new Child();
	}
}

若想指定调用父类中的有参构造函数,那么可在supper()中添加参数,指定调用父类中的某个构造函数,而且必须放在构造方法的第一条语句

【示例】指定调用父类构造方法

class Parent {
	String name;
	public Parent() {} // 无参构造方法建议加上!!!
	public Parent(String name) {
		this.name = name;
		System.out.println("parent 构造方法");
	}
}
class Child extends Parent {
	int age;
	public Child(String name, int age) {
		// super(形参列表) 必须放在构造方法的第一行
		super(name);
		this.age = age;
		System.out.println("Child 构造方法");
	}
	void show() {
		// 输出:name:小明 age:18
		System.out.println("name:" + name + " age:" + age);
	}
}
public class SuperDemo {
	public static void main(String[] args) {
		Child child = new Child("小明", 18);
child.show();
	}
}

super()和this()调用构造方法总结:

  1. super():调用父类中的某一个构造方法(必须为构造方法中的第一条语句)。
  2. this():调用本类中某一个构造方法(必须为构造方法中的第一条语句)。

super()和this()都必须在第一条语句,就证明super()和this()不可以同时出现在同一个构造方法中,其原因是super()保证在子类访问父类之前完成对父类的初始化操作,而this()保证父类初始化的唯一性。

thissuper 总结

this和super使用非常的相似,但是表现上却是大不相同,详情请看以下表格。

区别点thissuper
定义this代表本类对象的引用super代表父类存储空间
使用this.属性 this.方法 this()super.属性 super.方法() super()
调用构造调用本类构造,放在第一条语句调用父类构造,放在第一条语句
查找范围先从本类找,找不到查找父类直接查找父类,不查找子类

7、final关键字

final 的意思为最终,不可变。final 是个修饰符,它可以用来修饰类、类中的属性和方法和局部变量,但是不能修饰构造方法。

final的特点

1、final 修饰类不可以被继承,但是可以继承其它类。

class AA {}
final class BB extends AA {} // final修饰类可以继承其他类
class CC extends BB {} // 编译错误,final修饰类不可以被继承

2、final 修饰的方法不可以被覆盖,但子类的方法可以用final修饰。

class AA {
	final public void show1() {}
	void public show2() {}
}
class BB extends AA {
	final public void show1() {} // 编译错误,final修饰的方法不可以被覆盖
	final public void show2() {} // 父类中没有被final修饰方法,子类覆盖后可以加final
}

3、final 修饰的变量称为常量,这些变量只能赋值一次。

final修饰成员变量和静态变量,必须显示的设置初始值,JVM不会设置默认值

常量命名规则:多个有意义的单词连接,所有字符大写,单词之间用下划线分割。

public class FinalDemo {
	// 成员变量必须显示的设置初始值,JVM不会不会设置默认值。
	final String USER_NAME = "xiaoming";
	public static void main(String[] args) {
		// 多个有意义的单词连接,所有字符大写,单词之间用下划线分割.
		final int MAX_VALUE = Integer.MAX_VALUE; 
		// 编译错误,final 修饰的变量称为常量,这些变量只能赋值一次。
		MAX_VALUE = 120;
	}
}

4、final修饰的引用数据类型变量,变量中的地址不能改变,但是指向堆中对象的属性可以修改。

class Person {
	String name = "小明";
}
public class FinalDemo {
	public static void main(String[] args) {
		final Person p = new Person();
		p = new FinalDemo(); // 编译错误,地址值不能更改
		p.name = "小花"; // 地址内的对象属性值可以修改
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值