方法和封装

来自拉钩教育-JAVA就业集训营

构造方法的基本概念

  • 构造方法名与类名完全相同并且没有返回值类型,连void都不许有。

  • 语法:

class 类名 {
    类名(形参列表){
        构造方法体;
    }
}
  • 列子
class Person {
    person(){
        -Person类中的构造方法
    }
}
/*
    编程实现Person类的定义
*/
public class Person {
    
    String name; // 用于描述姓名的成员变量
    int age; // 用于描述姓名的成员变量
    
    // 自定义构造方法
    Person() {
        System.out.println("我就是自定义的构造方法!");
    }
    
    // 自定义成员方法实现所有特征的打印
    void show() {
        System.out.println("我是" + name + ",今年" + age + "岁了!");
    }
    
    public static void main(String[] args){
        
        // 1.声明一个 Person 类型的引用指向 Person 类型的悐
        Person p1 = new Person();
        // 并打印特征
        p1.show();
    }
}

默认构造方法

  • 当一个类中没有定义任何构造方法时,编译器会自动添加一个无参空构造构造方法,叫做默认/缺省构造方法,如:person(){}
  • 若类中出现了构造方法,则编译器不在提供任何形式的构造方法。

构造方法的作用

  • 使用new关键字创建对象时会自动调用构造方法实现成员变量初始化工作。
/*
    编程实现Person类的定义
*/
public class Person {
    
    String name; // 用于描述姓名的成员变量
    int age; // 用于描述姓名的成员变量
    
    // 自定义构造方法
    Person(String s, int i) {
        // System.out.println("我就是自定义的构造方法!");
        //name = "张飞";
        //age = 30;
        name = s;
        age = i;
    }
    
    // 自定义成员方法实现所有特征的打印
    void show() {
        System.out.println("我是" + name + ",今年" + age + "岁了!");
    }
    
    public static void main(String[] args){
        
        // 1.声明一个 Person 类型的引用指向 Person 类型的悐
        Person p1 = new Person("张飞", 30);
        // 并打印特征
        p1.show();
        
        Person p2 = new Person("关羽", 35);
        p2.show();
    }
}

案例题目(编程实现Point类)

  • 编程实现Point类的定义并想Point类添加构造方法
    • point()默认创建原点对象
    • Point(int i,int j)根据参数创建爱你点对象
/*
    编程实现Point类的定义
*/
public class Point {
    int x; // 用于描述横坐标的成员变量
    int y; // 用于描述纵坐标的成员变量
    
    // 自定义无参构造方法
    Point(){}
    
    // 自定义有参构造方法
    Point(int i, int j) {
        x = i;
        y = j;
    }
    
    // 自定义成员方法实现特征的打印
    void show(){
        System.out.println("横坐标是:" + x + ",纵坐标是:" + y);
    }
    
    public static void main(String[] args){
        
        // 1.使用无参方式构造对象并打印特征
        Point p1 = new Point();
        p1.show();
        
        // 2.使用有参方式构造对象并打印特征
        Point p2 = new Point(3, 5);
        p2.show();
    }
    
}

方法重载的概念

  • 若方法名称相同,参数列表不同,这样的方法之间构成重载关系(Overload)

重载的体现形式

  • 方法重载的主要形式体现在:参数的个数不同、参数的类型不同、参数的顺序不同,与返回值类型和形参变量名无关,但建议返回值类型最好相同。
  • 判断方法能否构成重载的核心:调用方法时能否加以区分。
/*
    编程实现方法重载主要形式的测试
*/
public class OverloadTest {
    
    // 自定义成员方法
    void show() {
        System.out.println("show()");
    }
    
    void show(int i){ // ok 体现在方法参数的个数不同
        System.out.println("show(int)");
    }
    
    void show(int i, double d){ // ok 体现在方法参数的个数不同
        System.out.println("show(int, double)");
    }
        
    void show(int i, int j){ // ok 体现在方法参数的类型不同
        System.out.println("show(int, int)");
    }
            
    void show(double d, int i){ // ok 体现在方法参数的顺序不同
        System.out.println("show(double, int)");
    }       
    
    // void show(double a, int b){ // error 与参数变量名无关
        // System.out.println("show(double, int)");
    // }
    
    // void show(double d, int i){ // error 与返回值类型无关
        // System.out.println("show(double, int)");
    // }
    
    public static void main(String[] args) {
        // 1.声明 OverloadTest 类型的引用指向该类型的对象
        OverloadTest ot = new OverloadTest();
        
        // 2.调用 show 方法
        ot.show();
        ot.show(66);
        ot.show(66, 3.14);
        ot.show(66, 14);
        ot.show(3.14, 14);
        // ot.show(3.14, 14);   
    }
}

练习题目(编程实现Point类)

  • 编程实现为Point类添加重载的成员方法:
    • up() - 实现纵坐标减1的功能。
    • up(int dy) - 实现纵坐标减去参数指定数值的功能。
  • 测试重载方法的调用规则
/*
    编程实现Point类的定义
*/
public class Point {
    int x; // 用于描述横坐标的成员变量
    int y; // 用于描述纵坐标的成员变量
    
    // 自定义无参构造方法
    Point(){}
    
    // 自定义有参构造方法
    Point(int i, int j) {
        x = i;
        y = j;
    }
    
    // 自定义成员方法实现特征的打印
    void show(){
        System.out.println("横坐标是:" + x + ",纵坐标是:" + y);
    }
    
    // 自定义成员方法实现纵坐标减1的行为
    void up() {
        y--;
    }
    // 自定义成员方法实现纵坐标减去参数指定数值的行为
    void up(int dy) {
        y -= dy;
    }
    
    public static void main(String[] args){
        
        // 1.使用无参方式构造对象并打印特征
        Point p1 = new Point();
        p1.show();
        
        // 2.使用有参方式构造对象并打印特征
        Point p2 = new Point(3, 5);
        p2.show();
        
        System.out.println("-----------------------------------------");
        
        // 3.调用重载的成员方法
        p2.up();
        p2.show();
        p2.up(2);
        p2.show();
        
    }
    
}

重载的实际意义

  • 方法重载的实际意义在于调用者只需要记住一个方法名就可以调用各种不同的版本,来实现各种不同的功能。
  • 如:java.io.PrintStream类中的 println 方法。

this的基本概念

  • 若在构造方法中出现了this关键字,则代表当前正在构造的对象。
  • 若在成员方法中出现了this关键字,则代表当前正在调用的对象。
  • this关键字本质上就是当前类类型的引用变量。
/*
    编程实现this关键字的使用
*/
public class ThisTest {
    
    // 自定义构造方法
    ThisTest(){
        // this代表当前正在构造的对象
        System.out.println("构造方法:this = " + this);
    }
    
    // 自定义成员方法
    void show() {
        // this代表当前正在调用的对象
        System.out.println("成员方法:this = " + this);
    }
    
    public static void main(String[] args) {
        
        // 1.声明ThisTest类型的引用指向该类型的对象
        ThisTest tt = new ThisTest();
        // 2.调用show方法
        tt.show();
        System.out.println("main方法中:tt = " + tt);
        
        
    }
}

this关键字工作原理

  • 在构造方法中和成员方法中访问成员变量时,编译器会加上 this. 的前缀,而 this. 相当于汉语中"我的",当不同的对象调用同一个方法时,由于调用方法的对象不同导致this关键字不同,从而 this. 方式访问的结果也就随之不同。

this关键字使用方式

  • 当局部变量名与成员变量名相同时,在方法体中会优先使用局部变量(就近原则),若希望使用成员变量,则需要在成员变量的前面加上 this. 的前缀,明确要求该变量是成员变量(重中之重)
  • this关键字除了可以通过 this. 的方式调用成员变量和成员方法外,还可以作为方法的返回值(重点)。
  • 在构造方法的第一个行可以使用this()的方式来调用本类中的其他构造方法(了解)。

引用变量的注意事项

  • 引用类型变量用于存放对象的地址,可以给引用类型赋值为null,表示不指向任何对象。
  • 当某个引用类型变量为null时无法对对象实施访问(因为他没有指向任何对象)。此时,如果通过引用访问成员变量或调用方法,会产生 NullPointerException 异常。

阶乘的计算方式

  • 编程实现参数n的阶乘并返回,所谓阶乘就是从1累成到n的结果。

  • 递推方式

/*
    编程实现累乘积的计算打印
*/
public class JieChengTest {
    // 自定义成员方法实现将参数 n 的阶乘计算出来并返回
    // 1!= 1; 2! = 1 * 2; 3! = 1*2*3;
    int show(int n) {
        // 递推
        int num = 1;
        for (int i = 1; i <= n; i++) {
            num *= i;
        }
        return num;
    }
    
    public static void main(String[] args) {
        //1.声明 JieChengTest类型的引用指向该类型的对象
        JieChengTest jct = new JieChengTest();
        // 2.调用方法进行计算并打印
        int res = jct.show(5);
        System.out.println("最终的计算结果是:" + res); // 120
    }
}

递归的基本概念

  • 递归本质就是指在方法体的内部直接或间接调用当前方法自身的形式。

  • 递归计算阶乘

/*
    编程实现累乘积的计算打印
*/
public class JieChengTest {
    // 自定义成员方法实现将参数 n 的阶乘计算出来并返回
    // 1!= 1; 2! = 1 * 2; 3! = 1*2*3;
    int show(int n) {
        // 递归的方式
        // 当n的数值为1是,则阶乘的结果就是1
        if (1 == n) return 1;
        // 否则阶乘的结果就是 n * (n -1)!
        return n * show(n - 1);
    }
    
    public static void main(String[] args) {
        //1.声明 JieChengTest类型的引用指向该类型的对象
        JieChengTest jct = new JieChengTest();
        // 2.调用方法进行计算并打印
        int res = jct.show(5);
        System.out.println("最终的计算结果是:" + res); // 120
    }
}

递归的注意事项

  • 使用递归必须有递归的规律以及退出条件。
  • 使用递归必须使得问题简单化而不是复杂化
  • 若递归影响到程序的执行性能,则使用递推取代之

费式数列的递归实现

  • 案例:
    • 编程实现费式数列中第n项的数值并返回。
    • 费式数列:1 1 2 3 5 8 13 21 ……
/*
    编程实现费式数列的计算并打印
*/
public class FeeTest {
    // 自定义成员方法实现费式数列中第n想数值的计算并返回,n由参数指定
    // 1 1 2 3 5 8 13 21 ……
    int show(int n) {
        // 1.使用递归的方式进行计算
        // 当 n = 1或者 n = 2时,结果是1
        if (1 == n || 2 == n) {
            return 1;
        }
        // 否则结果是前两项的和
        return show(n-1) + show(n-2);
    }
    
    public static void main(String[] args) {
        // 1.声明 FeeTest 类型的引用指向该类型的对象
        FeeTest ft = new FeeTest();
        // 2.调用方法计算并打印
        int res = ft.show(5);
        System.out.println("计算结果是:" + res); // 5
    }
}

费式数列的递推实现

/*
    编程实现费式数列的计算并打印
*/
public class FeeTest {
    // 自定义成员方法实现费式数列中第n想数值的计算并返回,n由参数指定
    // 1 1 2 3 5 8 13 21 ……
    int show(int n) {
        // 2.使用递推的方式进行计算
        int ia = 1;
        int ib = 1;
        for (int i = 3; i <= n; i++) {
            int ic = ia + ib;
            ia = ib;
            ib = ic;
        }
        return ib;
    }
    
    public static void main(String[] args) {
        // 1.声明 FeeTest 类型的引用指向该类型的对象
        FeeTest ft = new FeeTest();
        // 2.调用方法计算并打印
        int res = ft.show(55);
        System.out.println("计算结果是:" + res); // 5
    }
}

封装的概念

  • 通常情况下可以在测试类给成员变量赋值一些合法但不合理的数值,无论是编译阶段还是运行阶段都不会报错或者给出提示,此时与现实生活不符。
  • 为了避免上述错误的发生,就需要对成员变量进行密封包装处理,来隐藏成员变量的细节以及保证成员变量数值的合理性,该机制就叫做封装。

封装的实现流程

  • 私有化成员变量,private关键字修饰符。

  • 提供公有的get和set方法,并在方法体中进行合理值的判断。

  • 在构造方法中调用set方法进行合理值的判断。

  • 示例:

/*
    编程实现 Student 类的封装
*/
public class Student {
    // 1.私有化成员变量,使用 private 关键字修饰
    // private关键字修饰表示私有的含义,也就是该成员变量只能在当前类的内部使用
    private int id;      // 用于描述学号的成员变量
    private String name; // 用于描述姓名的成员变量
    
    // 3.在公有的构造方法中调用set方法进行合理值的判断
    public Student() {}
    public Student(int id, String name) {
        setId(id);
        setName(name);
    }
    
    // 2.提供公有的get和set方法,并在方法体重进行合理值的判断
    // 使用public关键字修饰表示公有的含义,也就是该方法可以在任意位置使用
    public int getId() {
        return id;
    }
    public void setId(int id) {
        if (id > 0) {
            this.id = id;
        } else {
            System.out.println("学号不合理哦!!!");
        }
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    // 自定义成员方法实现特征的打印
    // 什么修饰符都没有叫做默认的访问权限,界别结余private和public之间
    void show() {
        // System.out.println("我是" + name + ",我的学号是" + id);
        System.out.println("我是" + getName() + ",我的学号是" + getId());
    }
}

/*
    编程实现 Student 类的测试
*/
public class StudentTest {
    public static void main(String[] args) {
        // 1.声明 Student 类型的引用指向该类型的对象
        Student s1 = new Student();
        // 2.对成员变量进行赋值并打印
        // s1.id = -1001;
        // s1.name = "张飞";
        s1.setId(-1001);
        s1.setName("张飞");
        s1.show();
        
        System.out.println("------------------------------------------");
        
        // 3.使用有参方式构造对象的
        Student s2 = new Student(-1001, "张飞");
        s2.show();
        
    }
}

学生信息的录入

  • 案列题目
    • 提示用户输入班级的学生人数以及每个学生的信息,学生的信息有:学号、姓名,最后分别打印出来。
    • 提示:Student[] arr = new Student[num];

JavaBean的概念

  • JavaBean是一种Java语言写成的可重用组件,其他Java类可以通过反射机制发现和操作这些JavaBean的属性。
  • JavaBean本质上就是符合以下标准的Java类:
    • 类时公共的
    • 有一个无参的公共的构造器
    • 有属性,且有对应的get、set方法
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,252评论 6 516
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,886评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,814评论 0 361
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,869评论 1 299
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,888评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,475评论 1 312
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,010评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,924评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,469评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,552评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,680评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,362评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,037评论 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,519评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,621评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,099评论 3 378
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,691评论 2 361

推荐阅读更多精彩内容