0%

java-Day4——Static

类属性、类方法

有时希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份。

static修饰的结构:属性、方法、代码块、内部类

静态变量

对比静态变量与实例变量:

​ 1.个数:

​ 静态变量:内存空间只有一份,被类的多个对象共享。

​ 实例变量:类的每一个实例都保存着一份实例变量

​ 2.内存位置:

​ 静态变量:jdk6之前存放在方法区。 jdk7及之后,存放在堆空间

​ 实例变量:存放在堆空间的对象实体中

​ 3.加载时机

​ 静态变量:随着类的加载而加载,由于类只会加载一次,所以静态变量也只有一份

​ 实例变量:随着对象的创建而创建。每个对象拥有一份实例变量

​ 4.调用者

​ 静态变量:可以被类和实例调用

​ 实例变量:只能通过实例来调用

​ 5.消亡时机

​ 静态变量:随着类的卸载而消亡

​ 实例变量:随着对象的消亡而消亡

静态方法

  • 随着类的加载而加载

  • 可以通过“类.静态加载”,直接调用静态方法

  • 静态方法可以调用静态的属性和方法,但不可以调用任何非静态的结构

    但非静态方法可以调用当前类中的静态结构

什么时候需要将属性声明为静态的

  • 判断当前类的多个实例是否能共享此成员变量,且此成员变量的值是相同的
  • 常将一些常量声明为静态,如Math类中的PI

什么时候需要将方法声明为静态?

  • 方法内操作的变量如果都是静态变量(而非实例变量),则建议声明为静态方法
  • 常常将工具栏的方法声明为静态方法。比如Array类、Math类

单例设计模式(Singleton)

定义:某个类只能存在一个对象实例

实现思路

如果要让虚拟机只能产生一个对象。首先必须将类的构造器的访问权限设置为private,这样就不能用new操作符在类的外部产生类的对象了,但在类的内部可以产生该类的对象,因为在类的外部开始无法得到类的对象,只能通过调用类的某个静态方法以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以只能类内部产生的该类对象的变量也必须定义成静态的

具体实现方式

饿汉式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Bank{
//1.类的构造私有化
private Bank(){

}

//2.在类的内部创建当前实例
//4.此属性也必须声明为static
private static Bank instance = new Bank();

//3.使用getXXx()获取当前实例,必须声明为static
public static Bank getInstance(){
return instance;
}

}

//懒汉式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class GirlFriend{
//1.类的构造器私有化
private GirlFriend(){}

//2.声明当前类的实例
//4.此属性也必须声明static
private static GirlFriend instance = null;

//3.通过getXX()获取当前类的实例,如果未创建,则在方法内部创建
public static GirlFriend getInstance(){
if(instance ==null){
instance = new GirlFriend();
}
return instance;
}
}

特点对比

  • 饿汉式:立即加载,随着类的加载,当前唯一实例就创建了

  • 懒汉式:延迟加载,在需要使用时,进行创建了

优缺点

  • 饿汉式:写法简单,由于内存中较早加载,使用更方便、更快。是线程安全的。(缺点)内存中占用实际较长
  • 懒汉式:在需要时进行创建,节省内存空间。(缺点)线程不安全

Main方法

1
2
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Person{
public static void eat(){
sout("爸爸吃饭");
}
}

class Son extends Person{
public static void eat(){
sout("儿子吃饭");
}
}

Public class Test{
main(){
Person p1 = new Son();
p1.eat(); 输出的是爸爸吃饭

}
}

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修饰成员变量,能不能进行++操作

不能

-------------本文结束感谢您的阅读-------------