三、面向对象(下)

来源:互联网 发布:视频云平台 阿里云 编辑:程序博客网 时间:2024/06/05 03:26

注:博主是看《Java疯狂讲义》进行复习和总结的,所以博客里面的代码和举例部分是来自原书。加一些自己的个人理解在里面。。因为自己的总结还不够成熟,里面有些说法可能是不对的,希望大家看到错误指出来,我一定会改正 (づ ̄ 3 ̄)づ

一、Java8的增强包装类

1.包装类的基本概念。
把基本类型值包装成对象,
对象的特性:有成员变量、方法可以被调用。
包装类存在的意义:当需要用到Object类型的数值如1,2,3之类的,包装类就可以很好的解决这个问题。8种基本数据类型是不支持面向对象的。
基本数据类型对应的包装类有8种:

int                           Integerfloat                         Floatdouble                        Doublechar                          Charecterboolean                       Booleanshort                         Shortlong                          Longbyte                          Byte

2.Java支持自动装箱和拆箱:
自动装箱,基本类型变包装类
自动拆箱:包装类变基本类型(但是注意基本类型和包装类要匹配的)。利用了Java向上自动转型的特征。(子类向父类转,向上转)

3.基本类型变量与字符串之间的转换
(1)除了Charecter包装类意外,其他的包装类都提供了静态方法.ParseXX(“字符串”)
的方法来将字符串转换成前面那个XX类型
(2)字符串转换成其他类型包装类可以用:int a = new Integer(字符串名)
更简单的方法:String str = 5 + “”;

4.数值比较
有两种方式,一种是==,一种是a.equals(b),如果相等返回true,不相等返回false
但是注意,没有被重写过的equals方法是和==的效果一样的,String类的equals方法是被重写过的,用于比较两个字符串的内容是否相等。如果是两个引用类型的变量进行比较,比如Integer类型的包装类进行比较,那么使用==和equals进行比较的原理是一样的,都是比较这两个类型的地址值是否指向同一个对象。如果是返回true,否返回false。值得注意的是,在整形值进行比较的时候,-128~127之间Integer类型的使用==与比较是可以得出正确结果的,这是因为系统开辟了一块缓冲区(其实这个地方我也不是太懂,书上讲的有点复杂。。先记住吧),但是超过128的数字进行比较的时候就会按照他们引用的地址值是不是相等。
如果想按照自己意愿去比较的话,可以重写equals方法。可以按照自己的意愿在里面添加一些条件判断让他们返回true,比如判定两个对象是相等的

5.无符号整数
最高位不再当做符号位,因此不支持负数。不过。。这个有什么用处呢,我还不太清楚

二、处理对象
1.输出对象
如果直接输出对象的引用,那么输出的会是对象的地址值。如果想要输出的是详细描述的这个对象的信息,可以使用.toString()方法。不过如果直接使用对象.toString()的话,输出的是
类名+@+hashcode。因此如果想要输出用户期望的自定义描述的话,应该重写这个方法,重新定义对象的描述。
比如
public String toString(){
return “sdfsdfafdsfasf(描述信息)”;
}

2.equals方法
前面已经说得很清楚了关于equals和== 之间的相同和不同的。
不过使用equals需要满足下列条件:
自反性:对任意x,x.equals(x)一定返回true
对称性:对于x,y,如果x.equals(y)返回true,那么y.equals(x)一定返回true
传递性:对于x,y,z,如果x.equals(y) 为true,y.equals(z)为true,那么x.equals(z)一定返回true
一致性:对于任意的x,y如果对象中用于等价的信息没有变,那么无论调用x.equals(y)多少次,返回的结果应该保持一致,要么一直是true,要么一直是false。
对任何不是null的x,x.equlas(null)一定返回false

关于String有个地方,new String(“字符串”)到底产生了几个对象?和直接字符串有什么区别呢?
在new String(“字符串”)的时候,常量池里首先先存储了“字符串”,然后在使用new 的时候有创建了一个存着“字符串”内容的对象,因此应该是两个对象。

三、类成员
类成员包括 成员变量,方法,构造器,内部类。
1.static
被static修饰的即为类成员。static不可以修饰构造器(试想一下,构造器是在类初始化的时候被调用的。。是跟实例有关系的而不是在类建立的时候就被调用的。)
实例访问类成员的时候依旧是类的委托访问类成员。如果给这个实例赋值null之后就会发现 ,类.类成员 值仍然存在不受影响。但是再使用这个被赋值成null的对象再去引用类成员的时候就会引发NullPointerException异常
2.单例类:一个类始终只能创建一个实例。
为了保证一个类只能创造一个实例:构造器使用private来修饰,为了体现良好的封装原则,隐藏构造器应该给他提供一个public的访问方法,用于创建该类的对象。该方法必须使用static。(我想使用static的原因应该是这样的话这个方法就是属于这个类的,而且如果不是类的方法而是对象的方法,感觉就有点死循环了。。使用对象的方法来调用构造器并且限制它只能产生一个对象,有点说不过去。。。)然后在方法里面判断这个类产生的对象是不是空,如果是空的就调用这个方法,让构造器实例化一个实例,如果不是空的那么久使用已经存在的实例。这样就可以保证这个类是单例类。

四、final

final可以修饰,变量,方法
final修饰的值一旦初始化变不能再改变,因此他修饰成员变量和局部变量是不一样的。

1.final修饰成员变量
因为成员变量在定义的时候如果不给他赋值的话,系统会默认赋值,这个时候就相当于初始化一次。那么久不能在改变了,当然这样这个成员变量也就没有什么存在意义了。因此final在修饰成员变量的时候是必须要给其显式指定初始值的。

2.final修饰局部变量。
因为系统不会初始化局部变量,因此使用final修饰局部变量的时候需要一开始就指定初值

3.final修饰基本类型变量和引用类型变量的区别。
final修饰引用类型变量的时候,不变的是引用的值,而引用所指向位置的值却是可以变化的,

4.final修饰的方法
final修饰的方法不可以被重写。当父类里面的方法不希望被子类重写的时候就可以使用final来修饰。但是可以被重载
Object类的.getClass就是被final修饰的。
对于一个private方法,因为它仅在当前类中可见,如果在子类中出现了同名的方法,那是一个新方法,而不是重写。因为子类是见不到父类里被private修饰的方法的。

5.final修饰的类
final修饰的类不可以有子类。例如java.lang.Math就是被final修饰的方法类。它不可以有子类
有的是有有些类是不希望被继承,访问到它的内部数据的,这个时候就可以用final,让这个类不能被继承,保证了安全性。

6.不可变类,
这个类的意思是创建这个类的实例后,这个实例的实例变量是不可改变的。Java提供的8个包装类和java.lang.String类都是不可变类。

四、抽象类

1.抽象方法和抽象类。
二者都必须使用abstract来修饰。抽象类里面可以没有抽象方法。抽象方法不能有方法体。
抽象类不能被实例化,不能用new来创建实例,(如果用生孩子来比喻new实例。。那么抽象类就相当于一个概念,,概念怎么生孩子呢。。。对吧。。所以说是没有实例的)
抽象类可以包含成员变量,方法(普通,抽象均可),构造器,初始化块,内部类(接口,枚举)。
抽象类的构造器不能用于创建实例,它的构造器的作用是用于被子类调用。
含有抽象方法的类只能被定义成抽象类(就是说抽象类不一定含有抽象方法,但是抽象方法存在的类一定是抽象类)

注意:没有方法体和方法体为空是不一样的,没有方法体是直接没有{}。为空是有{},里面没有东西

2.抽象类的作用

(刚学的时候总是不太懂抽象类到底有啥用,感觉很多余。。)
以抽象类来做子类的模板,避免子类设计的随意性
抽象类体现的是一种模板类的模式设计。子类总体上会保留抽象类的行为方式。
模板模式也是常见的设计模式之一

五、Java8改进的接口

1.接口
接口定义的是多个类的公共行为规范,这些行为是与外部交流的通道,这就意味着接口里面通常定义的是一组公用方法。

2.Java8中接口的定义
interface关键字。
修饰符可以是public或者省略,如果省略了public访问控制符,则默认采用包权限访问控制符,即同一个包内可以访问。
一个借口可以有多个直接父接口。但是接口只能继承接口,不能继承类

注意:只有在Java8以上的版本才允许在接口中定义默认方法。类方法。

接口里的方法只能是抽象方法,类方法,默认方法

从某个角度来看,接口可以被当成一种特殊的类,因此一个Java源文件里最多只能有一个public接口,如果一个Java源文件里定义了一个public接口,则该源文件的主文件名必须与该接口名相同。

3.接口的继承
接口的继承和类的继承不一样,接口完全支持多继承。一个接口可以有多个直接父接口。使用extends关键字,多个父接口排在后面,用逗号隔开。

4.使用接口
一个类可以实现多个接口,也是对java的不灵活性的一个补充。implements
implements必须放在extends后面使用。
一个类实现了一个或者多个接口之后必须全部实现里面的抽象方法。否则该类将保留从父接口哪里继承到的抽象方法,这个类也就成了抽象类。

实现接口方法的时候,必须使用public访问修饰符。因为接口中的方法都是公用的。子类重写父类方法的时候访问权限只能大于等于。所以实现类实现接口的方法的时候只能使用public修饰符。

六、内部类
内部类可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以相互访问。但是外部类不能访问内部类的实现细节,例如内部类的成员变量,
匿名内部类适合创建那种只使用一次的类。

内部类比外部类多三个修饰符可以使用:private,protected,static
非静态内部类不能拥有静态成员

非静态内部类对象必须寄生在外部类对象里,

关于内部类的的名称:
局部内部类的calss文件总是遵循:外部类名字$内部类名字.class
当一个类里面可能有两个以上同名的局部内部类的时候,会在内部类名字前面加数字来区分

2.匿名内部类

定义匿名内部类不需要calss关键字。直接new出匿名内部类的子类来使用
匿名内部类必须继承一个父类或者实现一个接口。但最多只能继承一个父类或者实现一个接口。
匿名内部类不能使抽象类(抽象类没实例,抽象的匿名内部类没用 啊。所以不可能抽象的)
匿名内部类不能定义构造器。(匿名内部类是没有名字的。构造器是要和类名同名的。所以匿名内部类是没构造器的。可以通过初始化块来完成构造器的工作)

最常用的创建匿名内部类的方式是需要创建某个接口类型的对象。
例如:
对象.方法(传入仅用一次的实例);
传入仅用一次的实例:
new 接口(){
重写接口中的方法;
}

七、Java8新增的Lambda表达式(Java8的重要更新)

暂时跳过。。

八、对象与垃圾回收

(待更新。这个地方笔试考的还挺多的,指的仔细看一下。。这个改天补上)

原创粉丝点击