Java 高级特性2
关键字 static
无论是否产生了对象或无论产生了多少对象,某些特定的数据在内存空间里只有一份
如果想让一个类的所有实例共享数据,应该使用类变量
类变量:不用实例化,直接类名.属性名
就可以使用,是类的一部分,被所有这个类的实例化对象所共享,也可以叫做静态变量,用static
来修饰
实例变量:只有实例化后才能使用,属于实例化对象的一部分
类属性、类方法的设计思想
类属性作为该类各个对象之间共享的变量。在设计类时,分析哪些类属性不因对象的不同而改变,将这些属性设置为类属性。相应的方法设置为类方法。
如果方法与调用者无关,则这样的方法通常被声明为类方法,由于不需要创建对象就可以调用类方法,从而简化了方法的调用
使用范围
可用static修饰属性、方法、代码块、内部类
被修饰后的成员具备以下特点
随着类的加载而加载
优先于对象存在
修饰的成员,被所有该类的对象所共享
访问权限允许时,可不创建对象,直接被类调用
类方法
在static 方法内部只能访问类的static
属性,不能访问类的非static
属性
做工具类用最多
因为不需要实例就可以访问 static
方法,因此 static
方法内部不能有 this
和 super
重载的方法需同为 static
或非 static
单例设计模式
设计模式 就是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。即在实际编程中,逐渐总结出的一些解决问题的套路。
类的单例模式:采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。
例如:实例化对象的创建要消耗大量的时间和资源。
单例模式的实现方式
饿汉式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class Single {
/**
* 实现私有的构造函数,调用这个类的就不能直接用new来创建对象
*/
private Single(){}
// 私有的Single类变量,只能在类内部访问
private static Single single = new Single();
// getSingle() 为 static,不用创建对象即可访问
public static Single getInstance(){
return single;
}
public class Test {
public static void main(String[] args){
Single s1 = Single.getInstance(); // 访问静态方法
Single s2 = Single.getInstance();
if(s1==s2){
System.out.println("s1 is equals to s2!");
}
}
}懒汉式:最开始对象是null,直到有第一个人调用才new一个对象,之后都调用这个对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public class Single1 {
// 先私有化构造方法,保证在此类的外部,不能调用本类的构造器
private Single1(){}
// 先声明类的引用
private static Single1 single = null;
// 设置公有的方法来访问类的实例
public static Single1 getInstance(){
// 如果类的实例未创建,先创建,再返回给调用者
if (single==null){
single = new Single1();
}
// 若有了实例,直接返回给调用者
return single;
}
}
理解 main 方法的语法
由于 Java 虚拟机需要调用类的 main()
方法,所以该方法的访问权限是 public
,又因为 java 虚拟机在执行 main()
方法时不必创建对象,所以该方法是 static
的,该方法接收一个 String 类型的数组参数,该数组中保存执行 java 命令时传递给所运行的类的参数。
Java 运行的类名 第一个参数 第二个参数 第三个参数 … …
1 | public static void main(String[] args){} |
类的成员之四:初始化块
初始化块(代码块)作用:对Java对象进行初始化
程序的执行顺序:
声明成员变量默认初始化 -> 显式初始化、多个初始化块依次被执行(同级别下按先后顺序执行)-> 构造器再对成员进行赋值操作
1 | public class Test{ |
一个类中初始化块若有修饰符,则只能被 static
修饰,称为静态代码块,当类被载入时,类属性的声明和静态代码块先后顺序被执行,且只能被执行一次。
static
块通常用于初始化 static(类)属性
1 | class Person{ |
非静态代码块:没有 static 修饰的代码块
可以有输出语句
可以对类的属性声明进行初始化操作
可以调用静态和非静态的变量或方法
若有多个非静态代码块,那么按照从上到下的顺序依次执行
每次创建对象的时候,都会执行一次,且先于构造器执行
静态代码块:static 修饰的代码块
可以有输出语句
可以对类的属性声明进行初始化操作
- 不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法
- 若有多个静态代码块,那么按照从上到下的顺序依次执行
- 静态代码块的执行要先于非静态代码块
- 静态代码块只执行一次
在匿名类中,用代码块代替构造方法
关键字 final
在 Java 中声明类、属性和方法时,可以用关键字 final
来修饰,表示”最终“
final
标记的类不能被继承。 提高安全性,提高程序的可读性。
String 类、System 类、StringBuffer 类
final
修饰类
1 | final class A{ |
final
标记的方法不能被子类重写
Object 类中的 getClass()
final
标记的变量(成员变量或局部变量)即称为常量。名称大写,且只能被赋值一次。
final 标记的成员变量必须在声明的同时或在每个构造方法中或代码块中显式赋值,然后才能使用。
final
、static
一起修饰变量,称为全局变量。
常量定义名称约定使用大写,如果由多个单词组成名称,用 _
连接
抽象类(abstract class)
随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类。
用 abstract
关键字来修饰一个类时,这个类叫做抽象类;
用 abstract
来修饰一个方法时,该方法叫做抽象方法。
抽象方法:只有方法的声明,没有方法的实现。以分号结束:
1 | abstract int abstractMethod(int a); |
含有抽象方法的类必须声明为抽象类
抽象类不能被实例化。抽象类是用来作为父类被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍为抽象类。
不能用 abstract
修饰属性、私有方法、构造器、静态方法和 final
方法。
抽象类应用
抽象类是用来模型化那些父类无法确定全部实现,而是由其子类提供具体实现的对象的类。
模板方法设计模式(TemplateMethod)
抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为方式。
抽象类就像一个大纲,里面的抽象方法就是每个章节的标题。子类,去根据这些标题将每个章节细化出来。
解决的问题
当功能内部一部分实现是确定,一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现。
编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给其子类去实现,就是一种模板模式。
1 | public abstract class Template { |
接口
有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java 不支持多重继承。有了接口,就可以得到多重继承的效果。
接口(interface)是 抽象方法 和 常量值 的定义的集合
从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。
实现接口类:
1 | class SubClass implements InterfaceA{} |
一个类可以实现多个接口,接口也可以继承其它接口。
接口的特点
- 用
interface
来定义 - 接口中所有成员变量都 默认由
public static final
修饰 (全局常量) - 接口中所有方法都 默认是由
public abstract
修饰的 (抽象方法) - 接口没有构造器
- 接口采用多层继承机制
1 | public interface Runner{ |
实现接口的类必须实现提供接口中所有方法的具体实现内容,方可实例化,否则,仍为抽象类。
接口的主要用途是被实现类实现(面向接口编程)
与继承关系类似,接口与实现类之间存在多态性。
定义 Java 类的语法格式,先写 extends
,后写 implements
1 | <modifier> class <name> [extends <superclass>] [implements <interfce>[,<interface]*]{} |
一个类可以实现多个无关的接口。
与继承关系类似,接口与实现类之间存在多态。
如果实现接口的类中没有实现接口中的全部方法,必须将此类定义为抽象类。
抽象类是对于一类事物的高度抽象,其中既有属性也有方法;接口是对方法的抽象,也就是对一系列动作的抽象。
工厂方法(FactoryMethod)
工厂方法模式是设计模式中应用最为广泛的模式,在面向对象的编程中,对象的创建工作非常简单,对象的创建时机却很重要。FactoryMethod解决的就是这个问题,它通过面向对象的手法,将所要创建的具体对象的创建工作延迟到了子类,从而提供了一种扩展的策略,较好的解决了这种紧耦合的关系。
通过工厂把 new 对象隔离,通过产品的接口可以接收不同实际产品的实现类,实例的类名的改变不影响其他合作开发人员的编程。
类的成员之五:内部类
在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类。
Inner class 一般用于在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。
Inner class 的名字不能与包含它的类名相同
Inner class 可以使用外部类的私有数据,因为它是外部类的成员,同一个类的成员之间可相互访问。而外部类要访问内部类中的成员需要 内部类.成员
或者 内部类对象.成员
分类:
- 成员内部类(static 成员内部类和非static成员内部类)
- 局部内部类(不谈修饰符)、匿名内部类
内部类的特性
Inner class 作为类的成员
可以声明为
final
和外部类不同,Inner class 可声明为
private
或protected
Inner class 可以声明为
static
的,但此时就不能再使用外部类的非static
成员变量Inner class 作为类:
可以声明为
abstract
类,因此可以被其他内部类继承
【注意】:非 static 的内部类中的成员不能声明为 static
的,只有在外部类或 static
的内部类中才可以声明 static
成员
作用
主要解决 Java 不能多重继承的问题
- 本文作者: Kelly Liu
- 本文链接: http://tiantianliu2018.github.io/2019/10/07/Java-高级特性2/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!