java学习笔记——第八篇 面向对象之高级类特性
static关键字
在Java类中声明变量、方法和内部类时,可使用关键字static做为修饰符。
当一个类的多个对象拥有的某个属性一致的时候,例如所有的中国人都有个国家名称,每一个中国人都共享这个国家名称,传统的做法是为每个对象都单独分配一个用于代表国家名称的变量,这样的话会占用很多内存空间。因此我们希望多个对象能够共享这一个变量,此时就可以使用关键字static做为修饰符。
static修饰的成员也称类成员或静态成员。如:类变量、类方法、静态方法等。
类属性、类方法的设计思想
类属性作为该类各个对象之间共享的变量。在设计类时,分析哪些类属性不因对象的不同而改变,将这些属性设置为类属性。相应的方法设置为类方法。
如果方法与调用者无关,则这样的方法通常被声明为类方法,由于不需要创建对象就可以调用类方法,从而简化了方法的调用。
类变量、类方法
- 若需要一个类的多个对象共享一个变量,则该变量需要使用 static 修饰;
- static修饰的变量或方法由整个类(所有实例)共享,所以static 成员不属于某个类的实例,而属于整个类。如访问控制权限允许,可不必创建该类对象而直接用类名加‘.’直接访问静态成员(成员包括属性和方法);
- 没有对象的实例时,可以使用类名.方法名()的形式访问由static修饰的静态方法;
- 在静态方法里只能直接调用同类中其它的静态成员(包括变量和方法),而不能直接访问类中的非静态成员。这是因为,对于非静态的方法和变量,需要先创建类的实例对象后才可使用,而静态方法在使用前不用创建任何对象;
- 静态方法不能以任何方式引用this和super关键字。与上面的道理一样,因为静态方法在使用前不用创建任何实例对象,当静态方法被调用时,this所引用的对象根本就没有产生;
- 非静态方法中可以直接来访问类的静态成员;
- main() 方法是静态的,因此JVM在执行main方法时不创建main方法所在的类的实例对象,因而在main()方法中,我们不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员;
- 如果成员变量是静态的,生成的get或者set方法也是静态的。
静态初始化
静态初始化指对类的静态属性进行初始化。不应该在构造器中对静态成员进行初始化:如果在构造器中对静态成员进行初始化,那么每创建一个对象,都会对静态成员赋值;
非静态代码块:
// 非静态代码块
// 先于构造器执行,每创建一个对象都会执行一次
{
System.out.println("非静态代码块");
}
静态代码块:
// 静态代码块
// 在类被加载时执行一次,且仅执行一次,可以在静态代码块中对静态成员变量进行初始化.
// 先于非静态代码块和构造器执行.
public static int total,sum;
static{
System.out.println("静态代码块");
total = 200; // 初始化static(类)属性
sum = 300;
}
设计模式之单态(Singleton)模式
所谓类的单态设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。
- 不能在类的外部通过 new 关键字的方式创建新的实例: 构造器私有化。
- 在类的内部创建实例。
- 为了让类的外部能够访问到类的内部创建的实例, 该实例必须使用 static 修饰.
- 为了不允许在类的外部修改内部创建的实例的引用. SingleInstance.instance = null;
- 需要把该属性用 private 修饰
- 为了让外部进行读, 添加对应的 get 方法
class Single{
private static Single onlyone = new Single(); //私有的,只能在类的内部访问
private String name;
public static Single getSingle(){ //getSingle()为static,不用创建对象即可访问;变量是静态的,所以对应的get方法也为静态的
return onlyone;
}
private Single(){} //private的构造器,不能在类的外部创建该类的对象
}
public class TestSingle {
public static void main(String args[]){
Single s1 = Single.getSingle(); //访问静态方法
Single s2 = Single.getSingle();
if(s1==s2){
System.out.println("s1 is equals to s2!");
}
}
}
理解main方法的语法
由于java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public,又因为java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static的,该方法接收一个String类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数。
final关键字
在Java中声明类、属性和方法时,可使用关键字final来修饰。
- final标记的变量(成员变量或局部变量)即成为常量,只能赋值一次。final PI=3.14;
- final标记的类不能被继承。提高安全性,提高程序的可读性。
- final标记的方法不能被子类重写。增加安全性。
- final标记的成员变量必须在声明的同时或在每个构造方法中显式赋值,然后才能使用,否则编译出错。
- final在访问控制符后面,class的前面。
习惯用法:[访问限定符] [static] [final] [类型名]
抽象类(abstract 关键字)
- abstract 关键字可以修饰类和方法。
- 用abstract关键字来修饰一个类时,这个类叫做抽象类;用abstract来修饰一个方法时,该方法叫做抽象方法。
- 抽象类:不能被实例化,抽象类是用来被继承的,抽象类中不一定有抽象方法,如果有,抽象类的子类必须重写父类的抽象方法,并提供方法体。
- 抽象方法:没有方法体的方法,含有抽象方法的类必须被声明为抽象类,抽象方法是用来被子类重写的。抽象方法只有方法的声明,没有方法的实现,以分号结束。abstract int abstractMethod1( int a );
- 不能用abstract修饰私有方法,构造方法,静态方法。(因为私有方法、构造方法不能被子类继承;静态方法不属于面向对象范畴,直接用类点就可以调用,没有实现)。
- 抽象类是用来模型化那些父类无法确定全部实现,而是由其子类提供具体实现的对象的类。
接口(interface 关键字)
有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果(一个类可以实现多个无关的接口)。
接口(interface)是抽象方法和常量值的定义的集合,实际上接口更是一种规范(面向接口编程,包括JDBC,spring,用了接口编程的思想)。
从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。
接口的特点:
- 用 interface 来定义。
- 接口中的所有成员变量都默认是由public static final修饰的。在声明变量时必须直接赋值(因为接口中没有构造器),常量标识符的书写要求: 字母都大写, 多个单词使用 _ 连接
- 接口中的所有方法都默认是由public abstract修饰的。接口没有构造方法。
- 实现接口使用 implements 关键字. 若一个类既实现接口, 又继承了父类, 需要把 extends 关键字放在implements 前面, 即先继承父类, 后实现多个接口(可以这样理解:继承只能一个,实现可以多个,从少到多)。一个类可以实现多个无关的接口(模拟实现多继承), 若实现多个接口, 使用逗号分割。
- 接口也可以继承另一个接口,使用extends关键字。
关于接口的提示:
- 实现接口的类中必须提供接口中所有方法的具体实现内容。 若该类为抽象类, 另当别论
- 多个无关的类可以实现同一个接口
- 与继承关系类似, 接口与实现类之间存在多态性
- 如果实现接口的类中没有实现接口中的全部方法,必须将此类定义为抽象类。
- 如果实现的接口又继承了另外一个接口,那么这个实现类中要实现子接口和父接口的所有方法。
定义Java类的语法格式:
< modifier> class < name> [extends < superclass>][implements < interface> [,< interface>]* ] {
< declarations>*
}
内部类集匿名内部类
- 在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类
- 内部类和外层封装它的类之间存在逻辑上的所属关系
- Inner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。 Inner class的名字不能与包含它的类名相同;
- Inner class可以使用包含它的类的静态和实例成员变量,也可以使用它所在方法的局部变量;
- Inner class可以声明为抽象类 ,因此可以被其它的内部类继承。也可以声明为final的。
- 和外层类不同,Inner class可以声明为private或protected;
- Inner class 可以声明为static的,但此时就不能再使用外层封装类的非static的成员变量;
- 非static的内部类中的成员不能声明为static的,只有在顶层类或static的内部类中才可声明static成员。
学习来源:https://www.cnblogs.com/uncleyong/p/9729137.html