工作日志 5.4、5.5

这两天学习了疯狂Java讲义的第五章和第六章的一部分:

一、引用变量的强制类型转换

    类型转换运算符是小括号,用法如下:(type)variable。

    进行强制类型转换时需要注意:

    1.基本类型之间的转换只能在数值类型之间进行,这里所说的数值类型包括整数型、字符型和浮点型。但数值型不能和布尔型之间进行类型转换。

    2.引用类型之间的转换只能把一个父类变量转换成子类类型,如果是两个没有任何继承关系的类型,则无法进行类型转换。

    在进行类型转换之前,先用instanceof运算符判断是否可以成功转换,从而避免出现异常。


二、instanceof运算符

    Instanceof运算符的前一个操作数通常是一个引用类型的变量,后一个操作数通常是一个类(也可以是接口),它用于判断前面的对象是否是后面的类,或者其子类、实现类的实例。如果是,则返回true,否则返回false。

    在使用instanceof运算符时需要注意:instanceof运算符前面操作数的编译时类型要么与后面的类相同,要么是后面类的父类,否则会引起编译错误。


三、利用组合实现复用

class Animal
{
	private void beat()
	{
		System.out.println("心脏跳动...");
	}
	public void breath()
	{
		beat();
		System.out.println("吸一口气,吐一口气,呼吸中...");
	}
}
class Bird
{
	private Animal a;
	public Bird(Animal a)
	{
		this.a = a;
	}
	public void breath()
	{
		a.breath();
	}
	public void fly()
	{
		System.out.println("我在天空自在的飞翔...");
	}
}
class Wolf
{
	private Animal a;
	public Wolf(Animal a)
	{
		this.a = a;
	}
	public void breath()
	{
		a.breath();
	}
	public void run()
	{
		System.out.println("我在陆地上快速奔跑...");
	}
}
public class TestComposite
{
	public static void main(String[] args)
	{
		Animal a1 = new Animal();
		Bird b = new Bird(a1);
		b.breath();
		b.fly();
		Animal a2 = new Animal();
		Wolf w = new Wolf(a2);
		w.breath();
		w.run();
	}
}

    继承是对已有的类做一番改造,以此获得一个特殊的版本,就是将一个较为抽象的类改造成能适用于某些特定需求的类。如果两个类之间有明确的整体、部分关系,则应该采用组合关系实现复用。


四、单例类

    如果一个类始终只能创建一个实例,则这个类被称为单例类。

    为了避免其他类自由创建该类的实例,我们把该类的构造器使用private修饰,从而把该类的所有构造器隐藏起来。

    根据良好封装的原则:一旦把该类的构造器隐藏起来,则需要提供一个public方法作为该类的访问点,用于创建该类的对象,且该方法必须使用static修饰(因为调用该方法之前还不存在对象,因此调用该方法的不可能是对象,只能是类)。

    除此之外,该类还必须缓存已经创建的对象,否则该类无法知道是否曾经创建过对象,也就无法保证只创建一个对象。为此该类需要使用一个属性来保存曾经创建的对象,因为该属性需要被上面的静态方法访问,故该属性必须使用static修饰。

class Singleton
{
	//使用一个变量来缓存曾经创建的实例
	private static Singleton instance;
	//将构造器使用private修饰,隐藏该构造器
	private Singleton(){}
	//提供一个静态方法,用于返回Singleton实例
	//该方法可以加入自定义的控制,保证只产生一个Singleton对象
	public static Singleton getInstance()
	{
		//如果instance为null,表明还不曾创建Singleton对象
		//如果instance不为null,则表明已经创建了Singleton对象,将不会执行该方法
		if(instance == null)
		{
			//创建一个Singleton对象,并将其缓存起来
			instance = new Singleton();
		}
		return instance;
	}
}
public class TestSingleton
{
	public static void main(String[] args)
	{
		//创建Singleton对象不能通过构造器,只能通过getInstance方法
		Singleton s1 = Singleton.getInstance();
		Singleton s2 = Singleton.getInstance();
		//将输出true
		System.out.println(s1 == s2);
	}
}

五、final修饰符

    final关键字可用于修饰类、变量和方法,表示它修饰的类、方法和变量不可改变。

1.final修饰成员变量

    成员变量是随类初始化或对象初始化而初始化的。对于final修饰的成员变量而言,一旦有了初始值之后,就不能被重新赋值。所以成员变量只能在定义该成员变量时指定默认值,或者在静态初始化块、初始化块和构造器为成员变量指定初始值。

    final成员变量必须显示初始化,系统不会对final成员进行隐式初始化。

2.final修饰局部变量

    final修饰的局部变量可以在定义时指定默认值,也可在后面代码中对其赋值。

    由final修饰的形参不能被赋值。

3.final修饰引用类型变量

    使用final修饰的引用类型变量不能被重新赋值,但可以改变引用类型变量所引用对象的内容。

4.final方法

    final修饰方法不可被重写。

5.final类

    final修饰的类不可有子类。

6.不可变类

    不可变类的意思是创建该类的实例后,该实例的属性是不可变的。

    创建自定义的不可变类,可遵循以下规则:

*  使用private和final修饰符来修饰该类的属性。 *  提供带参数构造器,用于根据传入参数来初始化类里的属性。

*  仅为该类的属性提供getter方法,不要为该类的属性提供setter方法,因为普通方法无法修改final修饰的属性。

*  如果有必要,重写Object类中的hashCode和equals方法。在equals方法根据关键属性来作为两个对象相等的标准,除此之外,还应该保证两个用equals方法判断为相等的对象的hashCode也相等。

public class Address
{
	private final String detail;
	private final String postCode;
	//在构造器里初始化两个实例属性
	public Address()
	{
		this.detail = "";
		this.postCode = "";
	}
	public Address(String detail , String postCode)
	{
		this.detail = detail;
		this.postCode = postCode;
	}
	//仅为两个实例属性提供getter方法
	public String getDetail()
	{
		return this.detail;
	}
	public String getPostCode()
	{
		return this.postCode;
	}
	//重写equals方法,判断两个对象是否相等
	public boolean equals(Object obj)
	{
		if (obj instanceof Address)
		{
			Address ad = (Address)obj;
			if(this.getDetail().equals(ad.getDetail()) 
				&& this.getPostCode().equals(ad.getPostCode()))
			{
				return true;
			}
		}
		return false;
	}
	public int hashCode()
	{
		return detail.hashCode() + postCode.hashCode();
	}
}

六、抽象类

    抽象方法是只有方法签名,没有方法实现的方法。抽象方法和抽象类必须使用abstract修饰符来定义,有抽象方法的类只能被定义成抽象类,抽象类里可以没有抽象方法。

    抽象方法和抽象类的规则如下:

*   抽象类和抽象方法必须使用abstract修饰符来修饰。

*  抽象方法不能有方法体,抽象类不能被实例化,无法使用new关键字来调用抽象类的构造器创建抽象类的实例。

*  抽象类可以包含属性、方法(包括普通方法和抽象方法)、构造器、初始化块、内部类、枚举类六种成分。抽象类的构造器不能用于创建实例,主要是用于被其子类调用。

*  含有抽象方法的类(包括直接定义了一个抽象方法;继承了一个抽象父类,但没有完全实现父类包含的抽象方法;以及实现了一个接口,但没有完全实现接口包含的抽象方法三种情况)只能被定义成抽象类。

    当abstract修饰类时,表明这个类只能被继承;当abstract修饰方法时,表明这个方法必须由子类提供实现(即重写)。

    final和abstract不能同时使用,static和abstract不能同时修饰某个方法。

public abstract class Shape
{
	{
		System.out.println("执行Shape的初始化块...");
	}
	private String color;
	//定义一个计算周长的抽象方法
	public abstract double calPerimeter();
	//定义一个返回形状的抽象方法
	public abstract String getType();
	//定义Shape的构造器,该构造器并不是用于创建Shape对象,而是用于被子类调用
	public Shape(){}
	public Shape(String color)
	{
		System.out.println("执行Shape的构造器...");
		this.color = color;
	}
	public void setColor(String color)
	{
		this.color = color;
	}
	public String getColor()
	{
		return this.color;
	}
}



public class Triangle extends Shape
{
	//定义三角形的三边
	private double a;
	private double b;
	private double c;
	public Triangle(String color ,double a ,double b ,double c)
	{
		super(color);
		this.setSides(a,b,c);
	}
	public void setSides(double a ,double b ,double c)
	{
		if(a>=b+c || b>=a+c || c>=a+b)
		{
			System.out.println("三角形两边之和必须大于第三边");
			return;
		}
		this.a = a;
		this.b = b;
		this.c = c;
	}
	//重写Shape类的计算周长的抽象方法
	public double calPerimeter()
	{
		return a+b+c;
	}
	//重写Shape类的返回形状的抽象方法
	public String getType()
	{
		return "三角形";
	}
	public static void main(String[] args)
	{
		Shape s = new Triangle("黑色",3,4,5);
		System.out.println(s.getType());
		System.out.println(s.calPerimeter());
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值