类属性、类方法
有时希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份。
static修饰的结构:属性、方法、代码块、内部类
静态变量
对比静态变量与实例变量:
1.个数:
静态变量:内存空间只有一份,被类的多个对象共享。
实例变量:类的每一个实例都保存着一份实例变量
2.内存位置:
静态变量:jdk6之前存放在方法区。 jdk7及之后,存放在堆空间
实例变量:存放在堆空间的对象实体中
3.加载时机
静态变量:随着类的加载而加载,由于类只会加载一次,所以静态变量也只有一份
实例变量:随着对象的创建而创建。每个对象拥有一份实例变量
4.调用者
静态变量:可以被类和实例调用
实例变量:只能通过实例来调用
5.消亡时机
静态变量:随着类的卸载而消亡
实例变量:随着对象的消亡而消亡
静态方法
随着类的加载而加载
可以通过“类.静态加载”,直接调用静态方法
静态方法可以调用静态的属性和方法,但不可以调用任何非静态的结构
但非静态方法可以调用当前类中的静态结构
什么时候需要将属性声明为静态的
- 判断当前类的多个实例是否能共享此成员变量,且此成员变量的值是相同的
- 常将一些常量声明为静态,如Math类中的PI
什么时候需要将方法声明为静态?
- 方法内操作的变量如果都是静态变量(而非实例变量),则建议声明为静态方法
- 常常将工具栏的方法声明为静态方法。比如Array类、Math类
单例设计模式(Singleton)
定义:某个类只能存在一个对象实例
实现思路
如果要让虚拟机只能产生一个对象。首先必须将类的构造器的访问权限设置为private,这样就不能用new操作符在类的外部产生类的对象了,但在类的内部可以产生该类的对象,因为在类的外部开始无法得到类的对象,只能通过调用类的某个静态方法以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以只能类内部产生的该类对象的变量也必须定义成静态的
具体实现方式
饿汉式
1 | class Bank{ |
//懒汉式
1 | class GirlFriend{ |
特点对比:
饿汉式:立即加载,随着类的加载,当前唯一实例就创建了
懒汉式:延迟加载,在需要使用时,进行创建了
优缺点:
- 饿汉式:写法简单,由于内存中较早加载,使用更方便、更快。是线程安全的。(缺点)内存中占用实际较长
- 懒汉式:在需要时进行创建,节省内存空间。(缺点)线程不安全
Main方法
1 | public static void main(String[] args) { |
理解1:看作一个普通的静态方法
理解2:看作是程序的入口,格式的固定的
2.与控制台交互
方式1:使用Scanner
方式2:使用main()的形参进行传递
代码块
作用:用于初始化类或对象的信息
代码块的修饰:只能使用static进行修饰
具体使用:
1.静态代码块:
随着类的加载而执行
由于类的加载只有一次,进而静态代码块的执行,也只会执行一次
作用:用来初始化类的信息
内部可以声明变量、调用属性或方法、编写输出语句
静态先执行,非静态后执行
静态代码块内部只能调用静态结构
2.非静态代码块
- 随着对象的创建而执行
- 每创建当前类的一个实例,就会执行一次非静态代码块
- 作用:用来初始化对象的信息
- 内部可以声明变量、调用属性或方法、编写输出语句
- 可以调用静态结构和非静态结构
当赋值的值,一行代码没有办法获得该值时,我们可以考虑使用代码块
final关键字
final可以用于修饰类、方法、变量
类:表示此类不能被继承
比如:String,SringBuffer, StringBuilder{}
方法:表示此方法不能被重写
比如 Object类中getClasse()
变量:既可以修饰成员,也可以修饰局部变量。 此时变量其实变成了常量
1.final修饰成员变量:哪些位置可以给成员变量赋值?
- 显式赋值
- 代码块中
- 构造器中
2.final修饰局部变量,一旦赋值不能改变
- 方法内声明的局部变量:调用局部变量前,一定需要赋值,一旦赋值,不可更改
- 方法的形参:在调用此方法时,给形参进行赋值
final与static搭配修饰成员变量时:此成员变量称为全局常量
比如Math中的PI
经典题目
1.静态变量和实际变量区别和使用场景
2.静态方法是否可以被继承?是否可以被重写?
静态方法不能被重写。
父子类两同名方法,如果不是静态就是重写, 如果都是静态,就是两个独立的方法,静态方法不存在多态性。
但是可以重载
1 | class Person{ |
3.是否可以从一个static方法内部发出对非static方法的调用
不可以。 静态方法只能访问静态成员。
如果可以也只能通过对象来对非静态方法调用
4.被static修饰的成员(类、方法、成员变量)能否再使用private进行修饰
完全可以。除了代码块
5.main()方法的Public能不能换成private,为什么
可以改。但是改完以后不是程序入口了
6.main()方法是否可以调用非静态方法
只能通过对象来对非静态方法调用
7.类的组成和属性赋值执行顺序
8.静态代码块、普通代码块,构造方法,从类加载开始的执行顺序
静态代码块》普通代码块》构造器
9.对final的理解
10.使用final修饰一个变量时,是引用不能改变,引用指向的对象可以改变?
引用不能改变
引用指向的对象实体中的属性,如果没有final修饰,则可以改变
11.final不能用于修饰构造器方法
12. final或static final修饰成员变量,能不能进行++操作
不能