zoukankan      html  css  js  c++  java
  • Java核心技术——第5章

    类、超类和自类

    定义子类

    由继承Employee类来定义manager类

    public class Manager extends Employee//使用extends来定义继承
    {
    	...
    }
    

    Employee类称为超类、基类、父类

    manager类称为子类、派生类、孩子类

    子类可使用超类的方法、域

    应该将通用的方法放在超类中,而特殊用途的方法放在子类中

    覆盖方法

    在子类中添加一个与超类中同名的方法即可覆盖超类的方法

    在子类中不能直接访问超类的私有域,需要通过超类中的公有接口,如getSalary()

    子类想调用超类中同名的方法时,需要借助super关键字

    public double getSalary()
    {
    	return baseSalary + super.getSalary();
    }
    

    :super和this关键字由区别,super不是一个对象的引用,只能访问类中的方法,不能访问对象中的域,不能赋给一个对象变量,而this可以,例如,不能通过super.salary访问超类中的私有域

    子类构造器

    在子类中想使用超类的构造器,使用super关键字

    public Manager(String name,double salary,int year,int month,int day)
    {
    	super(name,salary,year,month,day);
    	bonus=0;
    }
    

    super调用超类构造器的语句必须在子类构造器的第一句

    子类没有显式调用超类构造器,则自动调用超类默认(没有参数)的构造器

    如果超类中没有不带参数的构造器,并且在子类构造器中没有显式调用超类其他构造器,则编译器报错

    继承层次

    由一个公共超类派生出来的所有类的集合被称为继承层次

    多态

    定义:一个对象可以指示多种实际类型的现象

    置换法则:程序中出现超类对象的任何地方都可以用子类对象置换

    对象变量是多态的,一个超类变量可以引用其任何的子类对象,但反过来就不成立,子类变量不能引用超类对象

    理解方法调用

    动态绑定:在运行时自动选择调用哪个方法的现象

    例:调用类C的对象x的方法,x.f(args)

    1. 编译器列出类C中所有名为f的方法,和其超类中访问属性为public且名为f的方法(超类的私有方法不可访问)

    2. 编译器查看调用方法时提供的参数类型

      如果找不到相应参数类型,则找可以类型转换之后的方法

      如果还是找不到,或者转换后的有多个方法,则报错

      方法名和参数类型为方法的签名,返回类型不是签名的一部分。可以允许返回子类型,即必须保证兼容性

    3. 如果是private方法、static方法、final方法或者构造器,则编译器可以准确知道应该调用哪个方法,称为静态绑定

    阻止继承:final类和方法

    对类使用final修饰符,表明该类不允许拓展

    public final class Executive extends Manager
    {
    	...
    }
    

    类中的特定方法被声明为final后,子类不能覆盖这个方法

    public class Employee
    {
    	public final String getName()
    	{
    		...
    	}
    }
    

    将类边设置为final之后,其中的方法都变成final,但是域不会变成final,final域表示构造对象之后就不能改变其值

    强制类型转换

    只能在继承层次内进行类型转换

    在将超类转换成子类之前,应该使用instanceof进行检查

    if(staff[1] instanceof Manager)
    {
    	boss = (Manager) staff[1];
    }
    

    应尽量避免使用类型转换和instanof运算法,往往强转是为了使用子类的方法,这说明超类设计不合理,应该重新设计超类

    抽象类

    关键字abstract

    为何要设置抽象类:将一些通用的方法放在继承通用超类中

    包含抽象方法的类必须被声明为抽象类

    抽象方法充当占位的作用,具体的实现放在子类中

    抽象类不能创建对象,但可以创建其子类的对象

    受保护类

    关键字protected

    超类中的某些方法或者某个域允许被子类访问

    访问修饰符总结

    1. private——仅对本类可见
    2. public——对所有类可见
    3. protected——对本包和所有子类可见
    4. 无修饰符——对本包可见

    Object:所有类的超类

    可以使用Object类型变量引用任何类型的对象,但是这个变量不能使用其中的域和方法,必须通过类型转换后才能

    Java中只有基本类型不是对象,所有数组类型都扩展了Object类

    equals方法

    Object类的equals方法用于检测两个对象是否具有相同的引用,通常没有意义

    相等测试与继承

    equals方法应具有的特性:

    1. 自反性:任何非空引用想,x.equals(x)为true
    2. 对称性:任何引用xy,x.equals(y)和y.equals(x)相等
    3. 传递性:任何引用xyz,若x.equals(y)为true,y.equals(z)为true,则x.equals(z)为true
    4. 一致性:如果xy引用的对象没有变化,则反复调用x.equals(y)应返回同样的结果
    5. 对于任意非空引用x,x.equals(null)为false

    image-20200414161436855

    常见错误:

    没有覆盖Object类中的equals方法,显式参数类型必须是Object

    @Override public boolean equals(Object other)
    

    可以在方法前添加标记,如果没有重写,则会报错

    hashCode方法

    散列码(hash code)是由对象导出的一个整数值。

    如果重定义equals方法,就必须重新定义hashCode方法,以便用户可以将对象插入散列表中

    toString方法

    用于返回对象值的字符串

    最好通过getClass().getName()获得类名的字符串,而不要将类名硬加到toString方法中,好处是,它的子类可以通过super来调用这个方法

    Object类定义了toString方法,默认打印对象所属的类名和散列码

    注:toString方法是一种非常有用的调试工具,每个类都应该增加toString方法

    泛型数组列表

    数组:

    Java中的数组允许在运行时确定数组大小

    int actualSize = ...;
    Employee[] staff = new Employee[actualSize];
    

    ArrayList:

    是一个采用类型参数的泛型类,具有自动调节数组容量的功能

    ArrayList<Employee> staff = new ArrayList<Employee>();
    ArrayList<Employee> staff = new ArrayList<>();//new后的类型可省略,检查前面的类型,然后放在后面
    

    使用add方法添加元素到数组列表

    staff.add(new Employee("Harry Hacker",...));
    

    如果add调用add且内部数组已满,则数组列表自动创建一个更大的数组,并把所有的对象拷到较大的数组中

    如果已经清楚数组可能存储的元素数量,则可以用ensureCapacity方法

    staff.ensureCapacity(100);
    

    可以在初始化时给出列表容量,并不是只能放这么多的元素,而是超出容量后会重新分配空间

    ArrayList<Employee> staff = new ArrayList<>(100);
    

    size方法返回数组列表包含的实际元素数量,相当于数组的length方法

    staff.size()
    

    一旦能确定数组列表大小不变,则使用trimToSize方法整理列表,但是之后再添加就要花时间移动存储块

    访问数组列表元素

    staff.set(i,harry);//相当于a[i]=harry;
    Employuee e = staff.get(i);//相当于Employee e = a[i];
    

    插入元素

    int n = staff.size()/2;
    staff.add(n,e);//位于n之后的元素都要向后移动一个位置,如果超出容量,则要重新分配空间
    

    可以使用for-each来遍历数组列表

    for(Employee e : staff)
    {
    	...
    }
    //等价于
    for(int i=0;i<staff.size();i++){
    	Employee e = staff.get(i);
    }
    

    类型化与原始数组列表的兼容性

    public void update(ArrayList list){...}
    public ArrayList find(String query){...}
    

    可以将类型化的数组列表传给update,如ArrayList<Employee>

    将原始类型的数组列表传给类型化的数组列表得到警告,但是不必做什么,在确定了转换没有问题后,可以用@SuppressWarnings("unchecked")来标注这个类型转换

    对象包装器与自动装箱

    将基本类型int放入ArrayList中,需要先包装成对象:Integer

    ArrayList<Integer> list = new ArrayList<>();
    

    对象包装器类是不可变的,一旦构造了包装器,则不能改变包装在其中的值

    对象包装器是final,不能创建子类

    自动装箱:

    自动将基本数据类型包装成相应的对象,放入数组列表中

    ArrayList<Integer> list = new ArrayList<>();
    list.add(3);//自动包装成Integer
    

    自动拆箱:

    int n = list.get(i);
    

    算数表达式中也能自动装箱自动拆箱

    Integer n = 3;
    n++;
    

    如果混合使用Integer和Double类型,Integer会自动拆箱,提升为Double,在装箱为Double

    还能将某些基本方法(静态方法)放置在包装器中,例如,将一个数字字符串转换成数值

    参数数量可变的方法

    printf方法的定义:

    public PrintStream printf(String fmt,Object... args){ return formot(fmt,args); }
    

    其中省略号表明该方法可以接收任意数量的对象,相当于Object[] args

  • 相关阅读:
    orm 锁 和 事务
    多表查询
    django 单表查询
    djgango装饰器
    几个SQL命令的使用
    怎么成为优秀的软件模型设计者?
    jbpm 工作流(二)
    Jbpm工作流(一)
    EJB 介绍
    JNDI 使用
  • 原文地址:https://www.cnblogs.com/xkf97/p/12704154.html
Copyright © 2011-2022 走看看