14_封装、继承
一. 方法的参数传递、返回值
Java语言在给被调用方法的参数赋值时,采用 传值(值传递) 的方式:
- 基本类型数据传递的是该数据的值本身;
- 引用类型数据传递的也是这个变量的值本身,即对象的地址(引用),而非对象本身.
1. 基本数据类型传递
//类
public class PassValue{
public void change(int x){
x = 100;
System.out.println("方法中x==" + x);
}
}
//类
public class Test{
public static void main(String[] args){
PassValue pv = new PassValue();
int x = 5;
System.out.println("方法调用之前x=="+ x);
pv.change(x); System.out.println("方法调用之后x==" + x);
}
}
2. 引用数据类型传递
数组、类、String(比较特殊特点:和基本类型一样).
public class PassValue2{
int x ;
public void change(PassValue2 obj){
obj.x = 100;
System.out.println(“方法中obj.x==” + obj.x);
}
}
public class Test{
public static void main(String[] args){
PassValue2 p = new PassValue2();
p.x = 5;
System.out.println(“方法调用之前p.x==” + p.x);
p.change(p);
System.out.println(“方法调用之后p.x==” + p.x);
}
}
3. 上机练习:
编写学生类:
学号,姓名,年龄,地址;
显示信息方法.
编写学生管理类:
输入学生信息(学生作为方法返回值);
修改学生信息(学生作为参数传递).
4. 基本类型和引用类型作为方法的返回值
基本类型返回的实际数据,引用类型返回的是对象的地址.
二. 封装性
Java语言有三大特征:
封装(encapsulation): 对外部不可见,隐藏对象的属性和实现细节.
继承(inheritance): 一个类继承另一个类的成员.
多态(Polymorphism): 每个对象表现的多样性.
1. 封装的概念
什么是封装:
在类中,对于不想被类外直接访问的成员变量,进行私有化,
同时对外提供一个公有的方法访问私有的成员.
封装成员变量两个步骤:
第一步: 添加private 修饰符;
第二步: 添加get和set方法.
2. private
使用private访问权限实现成员变量的私有化,private修饰的成员变量就是私有成员变量,只能在类内部直接访问,类外不能直接访问.
3. get和set方法
get方法表示访问私有属性的方法: 语法:
public 属性类型 getXxx(){ return 属性;
}
set方法表示修改私有属性的值的方法:
public void setXxx(参数类型 参数){ this.xxx = 参数;
}
示例
package com.syc.day09_4;
/**
* 人类
* 属性:姓名年龄性别
* 方法: eat study *
* 封装:(1)把成员变量变成私有的 (2) 添加get和set方法 * @author wgy
*
*/
public class Person {
private String name;
private int age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name=name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age>100||age<1) {
this.age=18;
}else {
this.age=age;
}
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
if(sex.equals("男")||sex.equals("女")){
this.sex=sex;
}else {
this.sex="男";
}
}
public void eat() {
System.out.println(name+"开始吃饭...");
}
public void study() {
System.out.println(name+"开始努力学习...");
}
public void show() {
System.out.println("姓名:"+name+" 年龄:"+age+" 性别:"+sex);
}
}
4. 类设计原则
- 成员变量(属性)私有化(用private修饰),添加get和set方法;
- 公开方法(用public修饰).
三. static关键字
static关键字只能修饰类成员: 修饰成员变量和方法.
1. 静态属性
所有本类对象所共有且相同的一个属性,是类的公用变量,不会随着对象的改变而改变的属性. 例如: 圆周率. 静态属性先于对象,不依赖于对象,可以直接通过类名直接访问(类名.属性 名).
示例
public class Person{
String name;
int age;
//人口总数
static int totalCount = 1300000000;
}
public class DemoPerson{
public static void main(String[]args){
//Person类中的totalCount属性是一个静态属性,
//可以直接通过类名访问
System.out.println(Person.totalCount);
}
}
2. 静态方法
所有本类对象所共有且相同的一个公共方法,属于类方法,先于对象的方法,不依赖于对象,可 以直接通过类名直接调用(类名.方法名()).
示例
public class Person{
static int totalCount;
public static void calcTotalCount(){
System.out.println("统计人口方法");
totalCount=1350000000;
}
}
public class DemoPerson{
public static void main(String[]args){
Person.calcTotalCount();
}
}
使用静态属性和方法使用原则:
-
- 如果这个变量或方法,不属于每个对象,属于整个类,就用静态;
-
- 如果这个对象只有一个,那么类中的属性和方法都用静态的,一般工具类中的方法静态的Arrays.方法名().
使用注意事项:
-
- 静态方法中可以直接访问静态变量,不能直接访问非静态变量;
-
- 非静态方法中可以直接访问静态变量和静态方法;
-
- 静态变量存在方法区中静态域中.
3. 代码块
代码块分类:
局部代码块、动态代码块、静态代码块.
局部代码块: 声明在方法中的代码块,执行时机与声明位置相关,提前释放变量(了解).
动态代码块: 又称构造代码块或实例代码块,声明在类体中的代码块,创建对象时自动执行一次,每创建一个对象就
执行一次动态代码块,进行一些初始化工作(了解).
静态代码块: 使用static关键字修饰的动态代码块,在类加载时自动执行,并只执行一次(掌握).
4. 静态导入(了解)
用import static代替import,静态导入包是JDK1.5中的新特性.
一般我们导入一个类都用: import com...ClassName;
而静态导入是这样: import static com...ClassName.*;
这里的多了个static,还有就是类名ClassName后面多了个.* ,意思是导入这个类里的 静态方法和属性.
静态导入前
public class Singleton {
public static void main(String [] args){
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.toHexString(36));
}
}
静态导入后
import static java.lang.System.out;
import static java.lang.Integer.*;
public class Singleton {
public static void main(String [] args){
out.println(MAX_VALUE);
out.println(Integer.toHexString(36));
}
}
这种方法建议在有很多重复调用的时候使用,如果仅有一到两次调用,不如直接写来的方便.
四. 继承性
1. 继承的概念
在原有类的基础上,产生一个新的类,在新的类中可以访问原有类中的非私有成员,并且可以添加一些自己独有的成员,这个过程叫做继承,简单理解就是一个类继承另外一个类.
2. 继承的好处
- 实现代码的重用和扩展;
- 模拟现实世界的关系.
3. 类的继承的使用
使用extends关键实现两个类的继承关系.
被继承的类可以被称为 父类,超类,基类.
继承的类可以被称为 子类,派生类.
继承的关系符合英语中 James2(二世) is a James1(一世) 的关系.
4. 继承的语法
public class FatherClass{
//属性
//方法
}
public class ChildClass extends FatherClass {
//属性
//方法
}
上机练习1:
编写Person类:
属性有: 姓名、年龄,出生日期;
方法有: showInfo();
编写Student类:
属性有: 姓名、年龄,出生日期、学校
方法有: showInfo(), study();
使用继承优化Student类.
public class Person {
String name;
int age;
String birthday;
public void showInfo() {
System.out.println("姓名:"+name+" 年龄:"+age+" 出生日期:"+birthday);
}
}
public class Student extends Person{
String school;
public void study(){
System.out.println(name+"好好学习天天向上");
}
}
上机练习2:
编写动物类(名字、颜色、品种),打印方法;
编写狗狗类(亲密度)和猫类(爱好)继承动物类;
狗狗类和猫类都有打印信息的功能;
狗狗有看家方法,猫类有玩球方法.
Animal类
package com.syc.day09_2;
/**
* 动物类
* (名字、颜色、品种),打印方法
*/
public class Animal {
//昵称
String name;
//颜色
String color;
//品种
String strain;
//打印信息
public void print() {
System.out.println("动物信息: 昵称:"+name+" 颜色:"+color+" 品种:"+strain) ;
}
}
Dog类
package com.syc.day09_2;
/**
* 狗狗类
*/
public class Dog extends Animal{
//亲密度
int love;
public void lookHome() {
System.out.println(name+" 正在给主人看家...........");
}
}
Cat类
package com.syc.day09_2;
/**
* 猫类
*/
public class Cat extends Animal{ //爱好
String hobby;
/**
* 玩球 *
*/
public void playBall() {
System.out.println(name+"正在玩球..........");
}
}
5. 子类对象实例化过程
-
先实例化父类对象:
默认调用父类默认构造方法. -
再实例化子类对象.
6. 不能被子类继承的成员
1).私有成员:私有成员不能被子类继承;
2).构造方法:父类中的构造方法不能被子类继承,但是会在子类的构造方法中调用(子类的构造方法中默认第一条语句是调用父类的默认构造方法).
7. 继承的特点:
1). 单继承: 一个子类只能有一个父类,一个父类可以有多个子类;
2). 传递性: 继承具有传递性.
五. super关键字
1. super关键字:用法和this类似
this 表示当前对象的引用.
this用法:
用法1: 调用本类的属性,可以解决成员变量名和局部变量名同名问题.
this.属性名
用法2: 调用本类的方法.
this.方法名
用法3: 调用本类中其他的构造方法.
this(参数);
注意,对于用法3来说需要注意2点:
1). 只能用在构造方法中,必须是第一条语句;
2). 只能调用一次.
2. super的概念
super表示当前父类对象的引用.
3. super的使用规则
1). super.属性: 表示访问父类中的属性,当子类中定义了与父类同名的属性时,若想在子类中访问父类的同名属性,需要使用super.属性访问;
2).super.方法: 表示调用父类中的方法,在子类中需要调用父类中没有被重写的方法时,需要使用super.方法调用;
3).super(): 表示调用父类的构造方法.
注意:
super()必须是子类构造方法中第一条语句.
子类中构造方法默认第一条语句会调用父类的无参数构造方法super(),也可以手动调用父类中带参数的构造方法.
4. 练习
public class Animal { //属性
String nickname;
String color;
String strain;
//默认构造方法
public Animal() {
System.out.println("父类Animal的构造方法执行了..........");
}
//带参构造方法()
public Animal(String nickname,String color,String strain) {
this.nickname=nickname;
this.color=color;
this.strain=strain;
}
//打印方法
public void print() {
System.out.println("本动物 昵称:"+nickname+" 颜色:"+color+" 品种:"+strain);
}
}
public class Dog extends Animal{
int love;
//默认构造方法
public Dog() {
super();//调用父类的默认构造方法
System.out.println("Dog子类的构造方法执行了");
}
//带参构造方法
public Dog(String nickname,String color,String strain,int love) {
super(nickname, color, strain);//调用父类的带参构造
this.love=love;
}
public void lookHome() {
System.out.println(nickname+"正在给主人看家....");
System.out.println("昵称:"+super.nickname);
System.out.println("颜色:"+super.color);
System.out.println("品种:"+super.strain);
System.out.println("亲密度:"+this.love);
super.print();
}
}
public class Test {
public static void main(String[] args) {
Dog afu=new Dog();
afu.nickname="阿福";
afu.color="黑色";
afu.strain="哈士奇";
afu.love=100;
afu.lookHome();
System.out.println("-------------");
//调用Dog的带参构造
Dog xiaohei=new Dog("小黑", "白色", "泰迪", 100);
xiaohei.lookHome();
}
}
5. this和super的区别:
(1). this表示当前对象的引用,super表示当前父类对象的引用;
(2). this.属性可以调用当前对象的属性包括继承的属性,super.属性可以调用父类的属性;
(3). this.方法()可以调用当前对象的方法包括继承的方法,super.方法()可以调用父类的方法;
(4). this(参数)调用本类中其他的构造方法,super(参数) 调用父类的构造方法;
(5). this(参数)和super(参数)只能用在构造方法中,必须是第一条语句,只能调用一次,不能同时使用.
六. 包和访问权限
为了便于管理大型软件系统中数目众多的类,解决类命名冲突的问题,Java引入了包(package).
在使用许多类时,类和方法的名称很难决定.有时需要使用与其他类相同的名称,包基本上隐藏了类并避免了名称上的冲突.
用package来声明包,package语句必须是java源文件中的第一条语句(若无这条语句,则放置在无名包下).
在package语句中,用"."来指明包(目录)的层次.
包对应着文件系统的目录层次结构.
一般使用公司或组织的域名的倒置+项目名或模块名来表示包名.
www.baidu.com 包名 com.baidu.oa www.alibaba.com 包名 com.alibaba.pay
1. 创建包
package com.syc.test;
public class Employee {
private String name; //姓名
private int age; //年龄
private double salary; //薪水
public Employee(){
}
public Employee(String name, int age, double salary){
//构造方法
this.name = name;
this.age = age;
this.salary = salary;
}
//getter和setter省略 }
2. 导入包
为使用定义在不同包中的Java类,需要import语句来引入所需要的类.
语法格式:
import package1[.package2...].类名
示例
import com.syc.test.Employee;
public class PackageDemo {
public static void main(String args[]){
Employee employee = new Employee();
}
}
注意:
要导入某个包中的所有类可以用: 包名.*
例如: import java.util.*;
在同一包中的类可以直接互相引用,无需import语句.
3. 访问权限

示例
package a;
public class Person{
public String name;
protected int age;
char sex;
private double sal;
public Person(){}
public Person(String name, int age, char sex, double sal){
this.name = name;
this.age = age;
this.sex = sex;
this.sal = sal;
}
public static void main(String[]args){
Person p = new Person("张三", 12, 'm', 5000);
System.out.println(p.name);
System.out.println(p.age);
System.out.println(p.sex);
System.out.println(p.sal);
}
}
package a;
public class Student extends Person{
public static void main(String[]args){
Person p = new Person("张三", 12, 'm', 5000);
System.out.println(p.name);
System.out.println(p.age);
System.out.println(p.sex);
//System.out.println(p.sal);
//同包子类中无法访问父类中私有成员
}
}
package a;
public class Demo{
public static void main(String[]args){
Person p = new Person("张三", 12, 'm', 5000); System.out.println(p.name);
System.out.println(p.age);
System.out.println(p.sex);
//System.out.println(p.sal);
//同包类中无法访问父类中私有成员
}
}
package b;
public class Student extends Person{
public static void main(String[]args){
Person p = new Person("张三", 12, 'm', 5000);
System.out.println(p.name);
System.out.println(p.age);
//System.out.println(p.sex);
//不同包中子类中无法访问默认权限成员
//System.out.println(p.sal);
}
}
package b;
public class Demo{
public static void main(String[]args){
Person p = new Person("张三", 12, 'm', 5000);
System.out.println(p.name);
//System.out.println(p.age);
//不同包中不能访问受保护属性
//System.out.println(p.sex);
//System.out.println(p.sal);
//不同包类中无法访问父类中私有成员
}
}
使用原则:
-
修饰类时: 只能public 或 默认的;
-
修饰成员变量和方法: 可以使用public、默认、protected、private;
-
局部变量不能访问权限修饰符.
七. 方法重载与重写
1. 方法重载(overload):
1>. 同一个类中,方法名相同,参数列表不同(个数不同,类型不同,顺序不同);
2>. 和方法返回值,访问修饰符无关.
2. 方法重写
在继承过程中,子类中从父类继承来的方法无法满足自己的需求时,可以在子类中对父类方法进行完善,这个完善过程叫做方法重写(override),方法的重写相当于在子类中覆盖父类中的方法.
示例
public class Animal { //属性
String nickname;
String color;
String strain;
//默认构造方法
public Animal() {
System.out.println("父类Animal的构造方法执行了..........");
}
//带参构造方法()
public Animal(String nickname,String color,String strain){
this.nickname=nickname;
this.color=color;
this.strain=strain;
}
//打印方法
protected Object printInfo() {
System.out.println("本动物 昵称:"+nickname+" 颜色:"+color+" 品种:"+strain);
return 10;
}
}
public class Dog extends Animal{
int love;
//默认构造方法
public Dog() {
super();//调用父类的默认构造方法
System.out.println("Dog子类的构造方法执行了");
}
//带参构造方法
public Dog(String nickname,String color,String strain,int love) {
super(nickname, color, strain);//调用父类的带参构造
this.love=love;
}
/**
* 看家
*/
public void lookHome() {
System.out.println(nickname+"正在给主人看家....");
}
/**
* 重写: 覆盖
* 1.方法名相同;
* 2.方法参数,返回值类型必须相同;
* 3.访问修饰符不能比父类严格.
* java特殊 1.7 返回值,可以和父类兼容就可以,
* 必须是引用类型
*/
public String printInfo() {
System.out.println("狗狗信息:昵称:"+super.nickname+" 颜色:"+super.color+" 品
种:"+super.strain+" 亲密度:"+this.love);
return "haha";
}
}
3. 方法重写规则
访问权限 其他修饰符 返回值 方法名(参数列表)
1. 在继承过程中,方法名、参数列表、返回值类型必须和父类相同;
2. 访问修饰符不能比父类严格.
Java特殊处:
JDK1.7之后,方法的返回值可以和父类兼容就可以,但是必须是引用类型.
4. 方法的重写和方法的重载的区别
方法的重载: Overload,在同一个类中,方法名相同,参数类别不同,互为重载方法.
方法的重写: Override,在继承过程中,在子类中重写父类中继承来的方法,方法名、参数列 表、返回值必须相同,访问权限不能比父类严格.
5. 有关方法重写之后的调用:
只要在子类中重写了父类的方法,通过子类对象调用该方法一定是子类重写的方法.
八. 总结
1. 方法传参、返回值:
方法传参采用传值:
基本类型传递的数据本身,引用类型传递的是地址;
返回值: 基本类型返回数据本身,引用类型返回地址.
2. 封装:
隐藏类的实现细节,保证程序安全.
2个步骤:
第一步: 私有化成员变量;
第二步: 添加get和set方法.
3. static关键字:
静态:
成员变量或方法属于所有对象共有的,不属于每个对象,使用静态.
4. 继承:
在原有类的基础上,产生一个新的类,在新的类中可以访问原有类中的非私有成员,并且可以添加一些自己独有的成员,这个过程叫做继承,简单理解一个类继承另外一个类.
关键字: extends
继承符合 is a 关系.
继承特点: 单继承;继承具有传递性.
5. super关键字:
表示当前父类对象的引用.
super.属性
super.方法
super(参数);
调用父类的构造方法;
this和super的区别.
6. 包:
管理类,解决类的命名冲突问题.
域名倒置+项目名:
package com.syc.day09; 必须是第一句.
导包:
import java.util.*;
7. 访问权限修饰符:
public: 公开的;
protected: 包含的;
[default]: 默认的;
private: 私有的.
类可以用 public 或默认的权限修饰符;
成员变量和方法 四个权限修饰符都可以用.
8. 方法重写:
重写规则:
①. 在继承中,方法名、参数列表、返回值必须和父类的方法相同;
②. 访问权限不能比父类更严格.