面向对象
ps:Java学习系列学的是李刚老师的《疯狂Java讲义》
instanceof 运算符
instaceof 运算符前一个操作数通常是一个引用类型变量,后一个操作数通常是一个类,用于判断前面的对象是否是后面的类,或者其子类、实现类的实例。如果是,返回 true,否则 false。
继承与组合
继承是实现类重用的重要手段,但继承破坏了封装
组合也是实现类重用的重要手段,而采用组合方式能提供更好的封装性。
为了保证父类有良好的封装性,不会被子类随意改变,设计父类通常应该遵循如下规则:
- 尽量隐藏父类的内部数据。尽量把父类的所有 Field 都设置为 private 访问类型
- 不要让子类可以随意访问、修改父类的方法。父类中那些仅为辅助其他的工具方法,应该使用 private 访问控制符叙事,让子类无法访问该方法;如果父类中的方法需要被外部类调用,则必须以 public 来修饰,但又不希望子类重写方法,可以使用 final 修饰符来修饰该方法;如果希望父类的某个方法被子类重写,但不希望被其他类自由访问则可以使用 ptotected 来修饰该方法。
- 尽量不要在父类构造器中调用将要被子类重写的方法。
class BaseClass
{
public BaseClass()
{
test();
}
public void test()
{
System.out.println("");
}
}
public class SubClass extends BaseClass
{
private String name;
public void test()
{
System.out.println(name.length());
}
public static void main(String[] agrs)
{
SubClass s = new SubClass();
}
}
上述程序系统试图创建SubClass对象时,会先执行父类构造器,父类构造器调用了子类重写的方法,变成调用子类重写后的方法,所以会引发空指针异常。
利用组合实现复用
组合是把旧类对象作为新类的Field嵌入,用以实现新类的功能,通常需要在新类里使用private修饰被嵌入的旧类对象。
class Animal
{
public void breath()
{
}
}
class Bird
{
//将原来的父类嵌入原来的子类,作为子类的一个组合成分
private Animal a;
public void breath()
{
}
}
Q:使用组合实现复用会导致系统开销增加吗?
A: 不会,继承实现复用时,创建一个子类,系统不仅需要为子类定义的Field分配内存空间,还需要为父类定义的分配空间。所以组合和继承所分配的空间相差不大,只是组合多一个引用变量来引用被嵌入的对象。
什么时候用继承?什么时候用组合呢?
继承是对已有的类作一番改造,依次获得一个特殊的版本。
组合则是两个类之间有明确的整体、部分的关系。
Java增强的包装类
Java是面向对象的编程语言,但是也包含了 8 种基本数据类型,这 8 种基本数据类型不支持面向对象的编程机制,也不具备对象的特性:没有 Field 、方法可以被调用。
为了解决 8 种基本数据类型的变量不能当成 Object 类型变量使用的问题,Java提供类包装类的概念。
基本数据类型 | 包装类 | 基本数据类型 | 包装类 |
---|---|---|---|
byte | Byte | char | Character |
short | Short | float | Float |
int | Integer | double | Double |
long | Long | boolean | Boolean |
8 个包装类除了 Character 之外,还可以通过传入一个字符串参数来构建包装类对象。
boolean bl = true;
Boolean b = new Boolean(bl);
int it = 5 ;
Integer i = new Integer(it);
Float f = new Float("4.56");
得到包装类对象中包装的基本类型变量:
boolean bl = b.booleanValue();
int i = it.intValue();
float f = fl.floatValue();
JDK 1.5 提供了自动装箱和自动拆箱功能:
//直接把一个基本类型变量赋给 Integer 对象
Integer it = 5;
//直接把一个 boolean 类型变量赋给一个 Object 类型变量
Object bl = true;
//直接把一个 Integer 对象赋给 int 类型变量
int i = it;
//先把 Object 对象强制类型转换为 Boolean 类型,再赋给 boolean 变量
boolean b = (Boolean)bl;
除此之外,包装类还实现基本类型变量和字符串之间的转换,把字符串类型的值转换为基本类型的值有两种方式:
1.利用包装类提供的 parseXxx(String s)静态方法(除了 Characte 都可以)
2. 利用包装类提供的Xxx(String s)构造器
String str = "123";
int i1 = Integer.parseInt(Str);
int i2 = new Integer(str);
String ftStr = String.valueOf(3.344f);
如果希望把基本类型转换成字符串,还有一种更简单的方法:
//intStr 的值为"5"
String intStr = 5 + "";
虽然包装类型的变量是引用数据类型,但是包装类的实例是可以与数值类型的值进行比较的,这种比较是直接取出包装类实例所包装的数值来进行比较的。
比较两个包装类的实例就复杂了,只有两个包装类引用指向同一个对象时才会返回true;