关键字:static
@[toc]
基本认识
- 当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上 的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象, 其方法才可以供外部调用。我们有时候希望无论是否产生了对象或无论产生了多少 对象的情况下,某些特定的数据在内存空间里只有一份,例如所有的中国人都有个 国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中 都单独分配一个用于代表国家名称的变量。
- static:静态的
- static可以用来修饰:属性、方法、代码块、内部类
- 使用static修饰属性:静态变量(类变量)
static修饰属性
1.1、属性,按是否使用static修饰,又分为静态属性和非静态属性(实例变量)
- 实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性,
当修改其中一个对象的非静态属性时,不会导致其他对象中同样的属性值的修改 - 静态变量:我们创建了类的多个对象,多个对象共享一个静态变量。
当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的
1.2、static修饰属性的其他说明:
- 静态变量随着类的加载而加载。可以通过“类.静态变量”的方式进行调用
- 静态变量的加载要早于对象的创建
- 由于类只会加载一次,则静态变量在内存中也只会存在一份,存在方法区的静态域中
- 调用关系
类变量(静态变量) | 实例变量 | |
---|---|---|
类 | yes | no |
对象 | yes | yes |
1.3、静态属性举例:Sysyem.out、Math.PI
1.4、类变量 vs 实例变量内存解析
使用static修饰方法
- 随着类的加载而加载,可以通过”类.静态方法“进行调用
类方法(静态方法) | 非静态方法 | |
---|---|---|
类 | yes | no |
对象 | yes | yes |
- 静态方法中,只能调用静态的方法或属性
- 非静态方法中,即可以调用静态方法和属性,也可以调用静态的方法和属性(以上两点都源自于他们的生命周期)
ps:粗暴理解来说,就是静态的先加载,随着类的加载就已经,无论方法还是属性,静态的不一定可以掉用非静态的,因为这时候非静态的还没加载但是静态的以经随着类加载了,但是非静态的一定可以调用静态的,因为非静态是随着对象而加载,当加载对象之后,静态的早就加载好了,所以可以调用静态的,不要死记硬背,从生命周期的角度去理解,类的声明周期和对象的生命周期
- static注意点:在静态的方法内,不能使用this关键字、super关键字
开发中去判别使用static
开发中,如何确定一个属性是否要声明为static?
- 这个属性可以被多个对象所共享的,这个属性不会随着对象的不同而不同
- 类中的常量也常常声明static(例如圆周率PI)
开发中,如何确定一个方法是否要声明为static?
- 操作静态属性的方法通常设置为静态
- 工具类中的方法,习惯上声明为static的。比如说:Math、Arrays、Collections
前面几点代码详解:
以上几点看完了可以看代码来理解
package day1.java1;
public class StaticTest {
public static void main(String[] args) {
Chinese.nation = "中国";//静态变量随着类的加载而加载,静态变量的加载要早于对象的创建
Chinese c1 = new Chinese();
c1.name = "小明";
c1.age = 12;
Chinese c2 = new Chinese();
c2.name = "小红";
c2.age = 13;
c1.nation = "china";
//static修饰方法
//通过对象调用方法
c1.eat();
//通过类进行调用
Chinese.show();
//类调用非静态方法会编译不通过
// Chinese.eat();
}
}
//中国人
class Chinese {
String name;
int age;
static String nation;//静态属性
public void eat() {//非静态方法
System.out.println("吃饭");
}
public static void show() {//随着类的加载而加载
System.out.println("我是一个中国人");
//不能调用非静态结构
// eat();
// name="tom";
//可以调用静态的结构
System.out.println(Chinese.nation);//这里的Chinese可以省略
}
public static void walk() {//静态方法
}
static关键字的应用举例
(结合代码和注释一起看)
package day1.java1;
//static关键字的应用
public class LxtCircleTest {
public static void main(String[] args) {
Circle c1 = new Circle();
Circle c2 = new Circle();
Circle c3 = new Circle(3.4);//调用第二个构造器
System.out.println("c1的id:"+c1.getId());//1
System.out.println("c2的id:"+c2.getId());//2
System.out.println("c3的id:"+c3.getId());//3
System.out.println("创建圆的个数:"+Circle.getTotal());
}
}
class Circle {
private double radius;//半径
private int id;//编号,自动赋值
public Circle() {//构造器给它一个赋值操作
id = init++;//这里的init属性加了static,内存之中只有1份init,所以没用一次构造器就会增加一次
total++;//
}
//给radius赋值
public Circle(double radius){
this();//可以在类的构造器中使用"this(形参列表)"的方式,调用本类中重载的其他的构造器
// id = init++
// total++;//上面的this();相当于调用了这里注释了的代码,因为可能调用不同的构造器,所以这个构造器也需要去进行init和total的增加
this.radius=radius;
}
private static int total;//记录圆的个数(造了几个圆的对象)
//希望id是自动赋值,从1开始
private static int init = 1;//多个对象共享,static声明的属性被所有对象共享,
public double findArea() {//求圆的面积
return Math.PI * radius * radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public static int getTotal() {//生成的get方法自动变成static,因为一个属性是static,通常操作这个属性的方法也是static
return total;
}
}
static练习题:账户信息
题目:编写一个类实现银行账户的概念,包含的属性有“帐号”、“密 码”、“存款余额”、“利率”、“最小余额”,定义封装这些 属性的方法。账号要自动生成。 编写主类,使用银行账户类,输入、输出3个储户的上述信息。 考虑:哪些属性可以设计成static属性。
答案代码:
测试类AccountTest
package day1.LXT;
public class AccountTest {
public static void main(String[] args) {
Account a1 = new Account();//建立账户1
Account a2 = new Account("000000",10000);//建立账户2
Account.setRate(0.02);
Account.setMinMoney(100);
//输出
System.out.println(a1.toString());//这里的toString方法可以省略
System.out.println(a2.toString());
System.out.println(a1.getRate());
System.out.println(a2.getMinMoney());
}
}
Account类
package day1.LXT;
/*编写一个类实现银行账户的概念,包含的属性有“帐号”、“密
码”、“存款余额”、“利率”、“最小余额”,定义封装这些
属性的方法。账号要自动生成。
编写主类,使用银行账户类,输入、输出3个储户的上述信息。
考虑:哪些属性可以设计成static属性。
*/
public class Account {
private int id;//账号(也自动生成)
private String password;//密码
private double money;//余额
private static double rate;//利率
private static double minMoney;//最小余额
//用于自动生成id
private static int init=1;
//构造器
public Account(){
id=init++;
}
public Account(String password,double money){
this();
this.password=password;
this.money=money;
}
//get和set方法
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String passwor) {
this.password = passwor;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public static double getRate() {
return rate;
}
public static void setRate(double rate) {
Account.rate = rate;
}
public static double getMinMoney() {
return minMoney;
}
public static void setMinMoney(double minMoney) {
Account.minMoney = minMoney;
}
@Override//重写toSting来输出用户属性
public String toString() {
return "Account{" +
"id=" + id +
", password=" + password +
", money=" + money +
'}';
}
}
id setMinMoney(double minMoney) {
Account.minMoney = minMoney;
}
@Override//重写toSting来输出用户属性
public String toString() {
return "Account{" +
"id=" + id +
", password=" + password +
", money=" + money +
'}';
}
}