Day17---学习Java第二弹

2021-07-27

对象和类

对象引用传递初步分析

引用传递的精髓:同一块堆内存空间,可以同时被多个栈内存所指向,不同的栈可以修改同

一块堆内存的内容。

下面通过若干个程序,以及程序的内存分配图,来进行代码的讲解。

我们来看一个范例:

class Person {     
         String name ;
         int age ;
         public void tell() {        
                   System.out.println("姓名:" + name + ",年龄:" + age) ;
         }
}
public class TestDemo {
         public static void main(String args[]) {
                   Person per1 = new Person() ;         // 声明并实例化对象
                   per1.name = "张三" ;
                   per1.age = 20 ;
                   Person per2 = per1 ;  // 引用传递
                   per2.name = "李四" ;
                   per1.tell() ;
         }
}

对应的内存分配图如下:

 

 再来看另外一个:

class Person {
         String name ;
         int age ;
         public void tell() {
                   System.out.println("姓名:" + name + ",年龄:" + age) ;
         }
}
public class TestDemo {
         public static void main(String args[]) {
                   Person per1 = new Person() ;         // 声明并实例化对象
                   Person per2 = new Person() ;
                   per1.name = "张三" ;
                   per1.age = 20 ;
                   per2.name = "李四" ;
                   per2.age = 30 ;
                   per2 = per1 ;// 引用传递
                   per2.name = "王五" ;
                   per1.tell() ;
         }
}

对应的内存分配图如下:

 

 垃圾:指的是在程序开发之中没有任何对象所指向的一块堆内存空间,这块空间就成为垃圾,所有的垃圾将等待GC(垃圾收集器)不定期的进行回收与空间的释放。

 

 

面向对象的封装性
封装(encapsulation)又叫隐藏实现(Hiding the implementation)。就是只公开代码单元的对外接口,而隐藏其具体实现。比如手机,手机的键盘,屏幕,听筒等,就是其对外接口。你只需要知道如何按键就可以使用手机,而不需要了解手机内部的电路是如何工作的。封装机制就像手机一样只将对外接口暴露,而不需要用户去了解其内部实现。

在研究封装性之前,先来看一段代码:

 1 package com.wz.classandobj;
 2 
 3 class Book{
 4 
 5     String title;
 6     double price;
 7 
 8     public void getInfo(){
 9         System.out.println("图书的名称:"+title+" 图书的价格:"+price);
10     }
11 }
12 
13 public class TestDemo {
14         public static void main(String args[]) {
15             Book book = new Book();
16             book.title = "Java开发";
17             book.price = -89.9;
18             book.getInfo();
19         }
20 }

 

 运行结果:

图书的名称:Java开发 图书的价格:-89.9

 

以上代码没有任何语法错误,却存在一个业务逻辑的错误,因为图书的价格不能为负数。造成这种情况的的原因在于:对象可以在一个类的外部直接访问属性。
如何解决?我们需要将Book类中的属性设置为对外不可见(只能是本类访问),可以使用private关键字来定义属性。

 

修改之前的代码如下:

 1 package com.wz.classandobj;
 2 
 3 class Book{
 4 
 5     private String title;
 6     private double price;
 7 
 8     public void getInfo(){
 9         System.out.println("图书的名称:"+title+" 图书的价格:"+price);
10     }
11 }
12 
13 public class TestDemo {
14         public static void main(String args[]) {
15             Book book = new Book();
16             book.title = "Java开发";
17             book.price = -89.9;
18             book.getInfo();
19         }
20 }

 

运行:

1 Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
2     The field Book.title is not visible
3     The field Book.price is not visible
4 
5     at com.wz.classandobj.TestDemo.main(TestDemo.java:16)

 

但是,要想让程序可以正常运行,那么必须让外部可以操作Book类的属性。在Java开发中,针对属性有这样的定义,在类中定义的属性都要求使用private声明,如果属性需要被外部所使用,那么按照要求,定义属性相应的setter和getter方法,以Book类中的String title 为例:
(1)setter方法是设置属性内容:

    public void setTitle(String t)

注意:有参数。

(2)getter方法是取得属性内容:

     public String getTitle()

注意:无参数。

范例:为Book类的封装属性设置setter和getter。

 1 package com.wz.classandobj;
 2 
 3 class Book{
 4 
 5     private String title;
 6     private double price;
 7 
 8     public String getTitle() {
 9         return title;
10     }
11 
12     public void setTitle(String title) {
13         this.title = title;
14     }
15 
16     public double getPrice() {
17         return price;
18     }
19 
20 
21     public void setPrice(double price) {
22         this.price = price;
23     }
24 
25     public void getInfo(){
26         System.out.println("图书的名称:"+title+" 图书的价格:"+price);
27     }
28 }
29 
30 public class TestDemo {
31         public static void main(String args[]) {
32             Book book = new Book();
33             book.setTitle("Java开发"); 
34             book.setPrice(-89.9);
35             book.getInfo();
36         }
37 }

运行结果:

图书的名称:Java开发 图书的价格:-89.9

发现,图书的价格是负数,需要加入检查业务逻辑错误的代码,可以在setter中增加验证,如果值为正,赋值,否则为默认值0.0:

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

对于数据验证,在Java标准开发中应该由辅助代码完成。在实际开发中,setter往往只是简单的设置属性内容,getter只是简单的取得属性内容。

开发建议:以后在定义类的时候,所有的属性都要编写private封装,封装之后的属性如果需要被外部操作,则编写setter、getter。

 

posted @ 2021-07-27 20:45  zrswheart  阅读(29)  评论(0编辑  收藏  举报