Java核心技术学习--第三天

第四章 对象与类

对象构造

重载

默认域初始化

必须明确地初始化方法中的局部变量,但是如果没有初始化类中的域,将会被自动初始化为默认值。

无参数的构造器

仅当类没有提供任何构造器的时候,系统才会提供一个默认的构造器。

显式域初始化

不管怎么调用构造器,每个实例域都可以被设置为一个有意义的初值。

参数名

在参数前面加上前缀“a”

public Employee(String aName, double aSalary)
{
	name = aName;
	salary = aSalary;
}

用同样的名字将实例域屏蔽起来,可以采用this.的形式访问实例域。this指示隐式参数。

public Employee(String name, double salary)
{
	this.name = name;
	this.salary = salary;
}

调用另一个构造器

构造器第一个语句形如this(···),这个构造器将调用同一个类的另一个构造器。

初始化块

首先运行初始化块。

java.util.Random

  • Random() 构造一个新的随机数生成器
  • int nextInt(int n) 返回一个0~n-1之间的随机数

对象析构与finalize方法

Java有自动的垃圾回收器,Java不支持析构器。
可以为任何一个类调用finalize方法,finalize方法将在垃圾回收器清除对象之前调用。

所有标准的Java包都处于java和javax包层次中。
使用包确保类名的唯一性。
嵌套的包之间没有任何关系。每一个都拥有独立的类集合。

类的导入

一个类可以使用所属包中的所有类,以及其他包中的公有类。
与包机制类似的是命名空间。

静态导入

可以使用System类的静态方法和静态域

import static java.lang.System.*;

将类放入包中

包作用域

标记为public的部分可以被任意的类使用;标记为private的部分只能被定义它们的类使用。如果没有指定,这个部分可以被同一个包中的所有方法访问。

包路径

设置类路径

文档注释

javadoc可以由源文件生成一个html文件。

注释的插入

编写注释

  • 公有类与接口
  • 公有的和受保护的构造器及方法
  • 公有的和受保护的域

注释以/**开始,*/结束。

类注释

import语句之后,类定义之前。

方法注释

@param变量描述
@return描述
@throws类描述,用于表示这个方法有可能抛出异常

域注释

对公有域建立文档

通用注释

@author姓名,可使用多个@author标记
@version文本(版本)
@since文本(始于)
@deprecated文本,添加一个不再使用的注释
@see引用

包与概述注释

产生包注释,需要在每一个包目录中添加一个单独的文件。

注释的抽取

类设计技巧

1、一定要保证数据私有
2、一定要对数据初始化
3、不要在类中使用过多的基本类型
4、不是所有的域都需要独立的域访问器和域更改器
5、将职责过多的类进行分解
6、类名和方法名要能够体现它们的职责。命名类名采用一个名词、前面有形容词修饰的名词或动名词。
7、优先使用不可变的类

第五章 继承

类、超类和子类

定义子类

关键字extends表明正在构造的新类派生于一个已存在的类。已存在的类为超类、基类或父类。新类称为子类、派生类或孩子类。

覆盖方法

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

super不像this是一个对象的引用,不能将super赋给另一个对象变量。super只是一个指示编译器调用超类方法的特殊关键字。

子类构造器

由于子类的构造器不能访问超类的私有域,则必须利用超类的构造器对这部分私有域进行初始化,可以通过super实现对超类构造器的调用。
使用super调用构造器的语句必须是子类构造器的第一条语句。
如果子类的构造器没有显式地调用超类的构造器,则将自动地调用超类默认的构造器。
如果超类没有不带参数的构造器,并且在子类的构造其中又没有显式地调用超类的其他构造器,则Java编译器将报告错误。
this用途:

  • 引用隐式参数
  • 调用该类其他的构造器
    super用途:
  • 调用超类的方法
  • 调用超类的构造器

继承层次

由一个公共超类派生出来的所有类的集合被称为继承层次。
从某个特定的类到其祖先的路径被称为该类的继承链。
Java不支持多继承。

多态

对象变量是多态的,一个超类对象既可以引用一个超类对象,也可以引用一个任何子类的对象。

理解方法调用

阻止继承:final类和方法

不允许扩展的类被称为final类。
类的特定方法声明为final,子类也不能覆盖这个方法。
如果将一个类声明为final,只有其中的方法自动成为final,不包括域。
如果一个方法没有被覆盖并且很短,编译器就能够对它进行优化处理,这个过程称为内联。

强制类型转换

将一个超类的引用赋给一个子类变量,必须进行类型转换。使用instanceof操作符查看是否能够成功转换。
注意事项:

  • 只能在继承层次内进行类型转换
  • 在超类转换成子类之前,使用instanceof进行检查
    尽量少使用类型转换和instanceof运算符。

抽象类

使用abstract关键字就不需要实现方法。
包含一个或多个抽象方法的类本身必须被声明为抽象的。
抽象类还可以包含具体数据和具体方法。
类即使不含抽象方法,也可以将类声明为抽象类。
抽象类不能被实例化。
可以定义一个抽象类的对象变量,但是它只能引用非抽象子类的对象。

Person p = new Student("Vince Wu", "Economics");

Person是抽象类,Student是非抽象子类。

受保护访问

超类中某些方法允许被子类访问,或允许子类的方法访问超类的某个域,需要将这些方法或域声明为protected。
Java中受保护部分对所有子类及同一个包中的所有其他类都可见。
4个访问修饰符:

  • 仅对本类可见–private
  • 对所有类可见–public
  • 对本包和所有子类可见–protected
  • 对本包可见–默认,不需要修饰符

Object:所有类的超类

Java中每个类都由Object扩展而来。
Java中,只有基本类型不是对象。

equals方法

相等测试与继承

hashCode方法

散列码是由对象导出的一个整型值。散列码是没有规律的。
每个对象都有一个默认的散列码,其值为对象的存储地址。
equals与hashCode的定义必须一致。

toString方法

toString方法用于返回表示对象值的字符串。

public String toString()
{
	return getClass().getName() 
		+ "[name=" + name
		+ ",salary=" + salary
		+ ",hireDay=" + hireDay
		+ "]";
}

使用toString方法的主要原因是:只要对象与一个字符串通过操作符“+”连接起来,Java编译就会自动调用toString方法。
Object定义的toString方法,用来打印输出对象所属的类名和散列码。

java.lang.Object

  • Class getClass() 返回包含对象信息的类对象
  • String toString() 返回描述该对象值的字符串。自定义类应该覆盖这个方法。

java.lang.Class

  • String getName() 返回这个类的名字
  • Class getSuperclass() 以Class对象的形式返回这个类的超类信息

泛型数组列表

ArrayList是一个采用类型参数的泛型类。

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

如果清楚可能存储的元素数量,可以填充数组之前调用ensureCapacity方法。

staff.ensureCapacity(100);

也可以把初始容量传给ArrayList构造器

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

size方法将返回数组列表中包含的实际元素数目。staff.size()相当于数组的a.length
能够确认数组列表的大小不再变化,就调用trimToSize方法。垃圾回收器将回收多余的存储空间。

java.util.ArrayList

  • ArrayList() 构造一个空数组列表
  • ArrayList(int initialCapacity) 用指定容量构造一个空数组列表
  • boolean add(E obj) 在数组列表的尾端添加一个元素,永远返回true
  • int size() 返回数组列表中的当前元素数量
  • void ensureCapacity(int capacity) 确保数组列表能够保存给定数量的元素
  • void trimToSize() 将数组列表的存储容量削减到当前尺寸

访问数组列表元素

使用get和set实现访问或改变数组元素的操作。
设置第i个元素

staff.set(i, harry);

获取数组列表的第i个元素

Employee e = staff.get(i);

原始的ArrayList类提供的get方法只能返回Object,所以get方法的调用者必须对返回值进行类型转换。(以前的版本)

Employee e = (Employee) staff.get(i);

既可以灵活扩展数组又可以方便地访问数组元素的方法

  • 首先,创建一个数组,添加所有元素。
ArrayList<X> list = new ArrayList<>();
while(···)
{
	x = ···;
	list.add(x);
}
  • 使用toArray方法将数组元素拷贝到一个数组中
X[] a = new X[list.size()];
list.toArray(a);

java.util.ArrayList

  • void set(int index, E obj) 设置指定位置的元素值
  • E get(int index) 获得指定位置的元素值
  • void add(int index, E obj) 向后移动元素,插入元素
  • E remove(int index) 删除一个元素,后面元素前移,返回被删除的元素

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

对象包装器与自动装箱

对象包装器类:Integer\Long\Float\Double\Short\Byte\Character\Void\Boolean
对象包装器类是不可变的,也不能定义子类。
定义整型数组列表,尖括号中的类型参数不允许是基本类型

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

由于每个值分别包装在对象中,ArrayList的效率远远低于int[]数组。
自动装箱:list.add(3)自动变换成list.add(Integer.valueOf(3))
自动拆箱:int n = list.get(i)自动变换成int n = list.get(i).intValue()
Integer对象是不可变的

java.lang.Integer

  • int intValue() 以int形式返回Integer对象的值
  • static String toString(int i) 以一个新的String对象的形式返回给定数值的十进制表示
  • static int parseInt(String s) 返回字符串s表示的整型数值(十进制整数)
  • static int parseInt(String s, int radix) 返回字符串s表示的整型数值(radix参数进制的整数)

java.text.NumberFormat

  • Number parse(String s) 返回数字值

参数数量可变的方法

允许将一个数组传递给可变参数方法的最后一个参数

System.out,printf("%d %s", new Object[] {new Integer(1), "widgets"});

枚举类

public enum Size
{
	SMALL("S"), MEDIUM("M"), LARGE("L"), EXTRA_LARGE("XL");
	private String abbreviation;
	private Size(String abbreviation) {this.abbreviation = abbreviation;}
	public String getAbbreviation() {return abbreviation;}
}

Size.SMALL.toString()将返回字符串"SMALL"
toString的逆方法是静态方法valueOf

Size s = Enum.valueOf(Size.class, "SMALL");

s设置成Size.SMALL
每个枚举类型都有一个静态的values方法,返回一个保护焊全部枚举值的数组。

Size [] values = Size.values();

ordinal方法返回枚举常量的位置。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值