• 【java核心技术】Java知识总结 -- 对象和类



    第4章 对象和类

    类和类之间的关系

    在类的关系中,最常见的关系有下面的三种

    • 依赖 ( “uses-a” )
    • 聚合 ( “has-a” )
    • 继承 ( “is-a” )

    用户自定义类

    可以定义自定义类的数组

    下面的代码通过创建自定义数组的方式定义了三个自定义类的数组,然后往该数组种存入该自定义类的对象

    package java核心技术卷一;
    
    import java.time.LocalDate;
    
    /**
     * @author weijiangquan
     * @date 2022/9/10 -18:34
     * @Description
     */
    
    
    public class EmployeeTest{
        public static void main(String[] args){
            Employee[] staff = new Employee[3];
            staff[0] = new Employee("dasd",1233,1987,12,10);
            staff[0] = new Employee("dasd",1233,1988,11,11);
            staff[0] = new Employee("dasd",1233,1989,10,22);
    
            for (Employee e:staff){
                e.raiseSalary(5);
            }
    
            for (Employee e:staff){
                System.out.println("name="+e.getName()+",salary="+e.getSalary()+",hireDay"+e.getHireDay());
            }
    
        }
    }
    
    
    class Employee{
        private String name;
        private double salary;
        private LocalDate hireDay;
    
        public Employee(String n,double s,int year,int month,int day){  
            name = n;
            salary = s;
            hireDay = LocalDate.of(year,month,day);
        }
    
        public String getName() {
            return name;
        }
    
        public double getSalary() {
            return salary;
        }
    
        public LocalDate getHireDay() {
            return hireDay;
        }
    
        public void raiseSalary(double byPercent){
            double raise = salary*byPercent/100;
            salary+=raise;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    image-20220910185203563

    image-20220910185215359

    对于下面的这种写法,虽然没有报错,但是确覆盖掉了类的属性中定义的变量。最终或许带来潜在的影响。以及对于后续的代码造成影响,如同一个定时炸弹,随时都会爆发。

        private String name;
        private double salary;
        private LocalDate hireDay;
    
        public Employee(String n,double s,int year,int month,int day){
            String name = n;
            double salary = s;
            hireDay = LocalDate.of(year,month,day);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    var

    在java10中,如果可以从变量的初始值推导出它们的类型,那么可以用var关键字声明局部变量,而无须指定类型。例如,可以不这样声明:

    Employee harry = new Employee("Harry Hacker",50000,1899,10,1);
    
    • 1

    而只需要写下面的代码:

    var Harry = new Employee("Harry Hacker",50000,1898,10,1);
    
    • 1

    这样就不需要重复书写类型名了

    如果不用了解任何java API就能从等号右边明显看出类型,在这种情况下我们都使用var表示法。不过我们不建议对数值类型使用var,如 int , long 或是 double ,使你不用担心 0 , 0L , 00 之间的区别。对于Java API有了更多的使用经验之后,你可能希望更多的使用var关键字。

    注意var关键字只能用于方法中的局部变量。参数和字段的类型必须声明

    方法参数

    java语言总是按值传递的,也就是说,方法得到的是所有参数值的以恶搞副本。具体来讲,方法不能修改传递给它的任何参数变量的的内容。

    对于上面的点,基础数据类型应该不用多说,比较有疑惑的地方可能是引用类型的。

    image-20220910221533518

    public static void swap(Employee x,Employee y){
        Employee temp = x;
        x = y;
        y = temp;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    想一下,如果Java对象采用的是按引用调用,那么这个方法就应该能够实现交换。

    image-20220910221748457

    最后发现其实是白费力气。在方法结束的时候参数变量 x 和 y 被丢弃了。原来的变量a和b仍然引用这个方法调用之前所引用的对象。

    image-20220910221956298

    这个过程说明: Java程序设计语言对对象采用的不是按引用调用,实际上,对象引用按值传递的。

    下面总结一下在Java中的对方法的参数能够做什么和不能做什么。

    • 方法不能修改基本数据类型的参数。(即数值类型或布尔类型)。
    • 方法可以改变对象参数的状态。
    • 方法不能让一个对象参数引用一个新的对象

    最后可以知道,虽然参数 x 和 参数 y 的的值交换了,但是 a 和 b 的没有受到任何影响。

    对象析构与finalize方法

    image-20220910223910981

    包的静态导入

    image-20220910224602280

    image-20220910224612700

    类设计技巧

    我们不会面面俱到,也不希望过于沉闷,所以在这一章结束之前先简单地介绍几点技巧。应用这些技巧可以使你设计的类更能得到专业OOP圈子的认可。

    1. 一定要保证数据私有。

      这是最重要的;绝对不要破坏封装性。有时候,可能需要编写一个访问器方法或更改器方法,但是最好还是保持实例字段的私有性。很多惨痛的教训告诉我们,数据的表示形式很可能会改变,但它们的使用方式却不会经变化。当数据保持私有时,表示形式的变化不会对类的使用者产生影响,而且也更容易检测 bug。

    2. 一定要对数据进行初始化。

      Java不会为你初始化局部变量,但是会对对象的实例字段进行初始化。最好不要依赖于系统的默认值,而是应该显式地初始化所有的数据,可以提供默认值,也可以在所有构造器中设置默认值。

    3. 不要在类中使用过多的基本类型。

      这个想法是要用其他的类替换使用多个相关的基本类型。这样会使类更易于理解,也更易于修改。例如,用 一个名为Address的新类替换一个Customer类中以下的实例字段:

    private String street;
    private String city;
    private String state;
    
    • 1
    • 2
    • 3

    这样一来,可以很容易地处理地址的变化,例如,可能需要处理国际地址。

    1. 不是所有的字段都需要单独的字段访问器和字段更改器。

      你可能需要获得或设置员工的工资。而一旦构造了员工对象,肯定不需要更改雇用日期。另外,在对象中,常常包含一些不希望别人获得或设置的实例字段,例如,Address类中的州缩写数组。

    2. 分解有过多职责的类。

      这样说似乎有点含糊,究竟多少算是“过多”?每个人的看法都不同。但是,如果明显地可以将一个复杂的类分解成两个更为简单的类,就应该将其分解(但另一方面,也不要走极端。如果设计10个类,每个类只有一个方法,显然就有些矫枉过正了)

    3. 类名和方法名要能够体现它们的职责。

      与变量应该有一个能够反映其含义的名字一样,类也应该如此(在标准类库中,也存在着一些含义不明确的例子,如 Date类实际上是一个用于描述时间的类)。

      对此有一个很好的惯例:类名应当是一个名词( Order),或者是前面有形容词修饰的名词( RushOrder),或者是有动名词(有“-ing”后缀)修饰的名词(例如,BillingAddress)。对于方法来说,要遵循标准惯例:访问器方法用小写get开头 ( getSalary),更改器方法用小写的set开头(setSalary)。

    4. 优先使用不可变的类

      LocalDate类以及java.time包中的其他类是不可变的——没有方法能修改对象的状态。类似plusDays的方法并不是更改对象,而是返回状态已修改的新对象。

      更改对象的问题在于,如果多个线程试图同时更新一个对象,就会发生并发更改。其结果是不可预料的。如果类是不可变的,就可以安全地在多个线程间共享其对象。

      因此,要尽可能让类是不可变的,这是一个很好的想法。对于表示值的类,如一个字符串或一个时间点,这尤其容易。计算会生成新值,而不是更新原来的值。

      当然,并不是所有类都应当是不可变的。如果员工加薪时让raiseSalary方法返回一个新的 Employee对象,这会很奇怪。

      本章介绍了有关对象和类的基础知识,这使得Java可以作为一种“基于对象”的语言。要真正做到面向对象,程序设计语言还必须支持继承和多态。Java提供了对这些特性的支持,具体内容将在下一章中介绍。

    对于最后一点或许你会有一定的疑惑,或许等到有一定的开发经历之后就发现吧。

  • 相关阅读:
    制作一个企业网站——html华为官网购物商城项目的设计与实现
    MySQL MVCC你了解吗
    数据结构与算法(一)线性结构篇
    java计算机毕业设计数据分析星辰网智能手机销售网站源码+系统+mysql数据库+lw文档+部署
    【giszz笔记】产品设计标准流程【4】
    kubeasz一键部署k8s集群
    Kotlin协程:StateFlow的设计与使用
    uniapp 自定义tabbar页面不刷新
    编程App软件优化是什么
    Maven高级---分模块设计,继承(继承关系/版本锁定/自定义属性)
  • 原文地址:https://blog.csdn.net/weixin_47994845/article/details/126801027