Java基础之面向对象(二)

前言

       本篇继续讲面向对象特性,自动装箱和拆箱,抽象和接口,内部类和lambda表达式,枚举类型等方面。

自动装箱、拆箱

       JDK 1.5之前,Java有8个基本数据类型不能当前Object类型,之后就才用自动装箱和拆箱,可以把一个基本数据类型直接赋值给包装类变量,也可以把包装类对象直接复制给一个对应的基本数据类型。

类成员

       用static关键字修饰的成员就是类成员,static语义代表的是修饰的对象属于整个类而不属于任何实例。

       Java中只能包括五种:成员变量、方法、构造器、初始化块、内部类(包括接口、枚举)、以static修饰的成员就是类成员,他能修饰除构造器之外的其他四种。

单例

       在一些特殊场景下,要求不允许自由创建该类的对象,而只允许为该类创建一个对象,为了避免该类被自由创建,类的构造器使用private修饰,从而把该类的所有构造器隐藏起来。但是还要有一个public方法作为该类的访问点,用于创建该类的对象,且该方法必须使用static修饰,除此之外,该类还不许知道已经缓存过已经创建的对象,否则该类无法知道是否创建过该对象。下面就手写代码实现一个单例类:

1
2
3
4
5
6
7
8
9
10
11
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

       但是这也只是懒汉,单线程情况,还有几种写法参考博客:单例的5种写法

final修饰符

       final关键字可以修饰类、变量和方法,用于它修饰的类,方法和变量不可变,类似C#中的sealed。修饰变量包括成员变量和局部变量和形参。准确说是一旦赋类初始值就不能被改变。final还可以完成C中宏定义的类似功能。

final成员变量

       final修饰的成员变量必须由程序员显式的指定初始值。

final局部变量

        系统不会对局部变量进行初始化,局部变量必须由程序员显式初始化。但是用final修饰局部变量时,既可以在定义时,指定默认初始值,也可以不指定。

final修饰基本变量和引用变量区别

       当使用final修饰基本变量时,不能对基本变量类型进行重新赋值,但对引用来说,仅仅是一个引用地址,final只能保证引用类型变量指定的地址不会改变,一直引用一个对象,但这个对象完全可以发生改变。

final方法

       不想子类重写的可以用final修饰,比如Object中的getClass()方法。

final类

       final类不能使用子类,比如Math类就是。保证不能被继承。

抽象

       当编写一个类时候,常常会给类定义一些方法,比如形状类Shape,应该提供一个计算周长的方法,但是Shape类型不同计算周长方式不同,这时我们可以使用抽象方法,只有方法签名,没有方法实现。

抽象类和抽象方法

  1. 都必须使用abstract修饰符来定义,有抽象方法的类只能被定义为抽象类,抽象方法不能有方法体。
  2. 抽象类不能被实例化,无法使用new来调用构造器实例对象,即使不包含抽象方法。
  3. 抽象类可以包含成员变量、方法、构造器、初始化块、内部类5个成分。主要作用是被其子类调用。
  4. 含有抽象方法的类:包括直接定义来一个抽象方法,继承一个抽象父类,但没有完全实现父类包含的抽象方法,或者实现了一个接口但没有完全实现接口包含的抽象方法这三种情况)只能被定义为抽象类。
  5. 不能用来修饰成员变量、局部变量、构造器。
  6. static和abstract不同时修饰一个方法,即没有所谓的类静态抽象方法。但也不是绝对互斥,它们可以修饰内部类。
  7. private和abstract不同时修饰方法。

接口

       在Java8中对接口进行了改进,允许接口中定义默认方法,默认方法可以提供方法实现。默认方法必须使用default修饰,且不能被static修饰。

概念

       接口是从多个相似类中抽象出来的规范,规范了它实现类的基本行为规范。接口使用interface关键字。仿佛默认使用public修饰。

       Java8中允许接口中定义类方法,必须使用statci修饰,该方法可以使用接口来调用。

       接口成员默认使用public static final修饰。

特性

  1. 接口支持多继承;
  2. 接口不能创建实例;
  3. 接口的实现类 implents;实现类可实现多个接口。

抽象和接口的比较

       一般接口来控制行为规范,抽象类用来定型。当你关注一个事物的本质的时候,用抽象类;当你关注一个操作的时候,用接口。

参考这篇博客:抽象和接口的区别

面向接口编程

实现简单工厂模式

详解工厂模式三种类型

实现命令模式

Java命令模式实现

内部类

非静态内部类

  1. 非静态内部类可以访问外部private成员。
  2. 优先在局部变量中寻找。
  3. 外部不能访问非静态内部类的private成员。
  4. 非静态内部类中不能定义静态成员。

静态内部类

  1. 静态内部类中可以包含静态、非静态成员都可以。
  2. 静态类不能访问外部成员,只能是访问静态成员。
  3. 静态内部类是外部类的一个静态成员,因此外部类的所有成员可以使用静态内部类来定义,创建对象,但是不能直接访问静态内部类的成员。
  4. 接口中也能定义内部类,接口中只能是静态内部类,默认使用public static。

内部类的使用

  1. 外部类内部使用内部类:和普通类没有太大区别,唯一区别是:不要在外部类中的静态成员中使用非静态的内部类。
  2. 在外部类以外使用非静态内部类:如果希望被访问,不能使用private。
  3. 外部类以外访问静态内部类,无须实例外部类。
  4. 局部内部类,在方法里,只能在方法内使用。

匿名内部类

       适合创建那种只需要一次使用的类,类如命令模式中的command对象。匿名内部类必须继承一个父类或实现一个接口,但最多继承一个父类或实现一个接口。不允许为抽象类,不能定义构造器,因为没有类名,但可以定义初始化块来完成构造器要完成的事情。

       在Java8之前,Java要求局部内部类、匿名内部类访问的局部变量必须使用final修饰,从Java8开始这个限制被取消了,Java8更加智能,自动添加final。

       参考这篇博客:匿名内部类总结

lambda表达式

       允许用更简单的代码来创建只有一个抽象方法的接口,即函数式接口。lambda表达式完全可用于简化创建匿名内部类对象。

       参考这篇博客:lambda表达式总结

枚举类

       早期会用简单的静态变量来表示枚举,但是类型不安全,没有命名空间,意义不明确,后来用类来封装,但是额外要写代码,JDK1.5之后增加了对枚举类的支持。enum。

       参考这篇博客:lambda表达式总结

说明

  文中出现的图片,文字描述有些来自互联网,但是出处无法考究,如果侵犯您的相关权益,请联系我,核实后我会马上加上转载说明。谢谢!!!