14_Java筑基之封装、继承

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();
    } 
}

使用静态属性和方法使用原则:

    1. 如果这个变量或方法,不属于每个对象,属于整个类,就用静态;
    1. 如果这个对象只有一个,那么类中的属性和方法都用静态的,一般工具类中的方法静态的Arrays.方法名().

使用注意事项:

    1. 静态方法中可以直接访问静态变量,不能直接访问非静态变量;
    1. 非静态方法中可以直接访问静态变量和静态方法;
    1. 静态变量存在方法区中静态域中.

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. 方法重写: 
   重写规则:
   ①. 在继承中,方法名、参数列表、返回值必须和父类的方法相同;
   ②. 访问权限不能比父类更严格.
发布了234 篇原创文章 · 获赞 74 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/syc000666/article/details/102817465