12、关键字static

关键字static

static 定义属性

问题引出:

class Book {
    private String title;
    private double price;
    // 为操作方便,暂不封装
    String pub = "清华大学出版社";

    public Book(String title, double price) {
        this.title = title;
        this.price = price;
    }

    public String getInfo(){
        return "书名:" + this.title + ",价格:" + this.price + ",出版社:" + this.pub;
    }
}

public class Demo {
    public static void main(String[] args) {
        Book bkA = new Book("Java开发", 79.5);
        Book bkB = new Book("JSP", 45.6);
        System.out.println(bkA.getInfo()); // 清华大学出版社
        System.out.println(bkB.getInfo()); // 清华大学出版社
        bkB.pub = "北京大学出版社";
        System.out.println(bkA.getInfo()); // 清华大学出版社
        System.out.println(bkB.getInfo()); // 北京大学出版社
    }
}

对上述代码进行内存分析:
在这里插入图片描述
通过内存分析,发现属性重复:每个对象各自占有相同的属性值。假如有1000个该对象,要修改所有对象的pub属性,就需要分别进行修改。因此如果将pub属性定为普通属性,那每个堆内存都保存有各自的pub值。

1.但所有对象的pub值都一样,应将其定为一个共享的属性,即所有对象都指向同一块pub属性。可以利用static定义共享属性。

class Book {
    private String title;
    private double price;
    // 为操作方便,暂不封装
    static String pub = "清华大学出版社";

    public Book(String title, double price) {
        this.title = title;
        this.price = price;
    }

    public String getInfo(){
        return "书名:" + this.title + ",价格:" + this.price + ",出版社:" + this.pub;
    }
}

public class Demo {
    public static void main(String[] args) {
        Book bkA = new Book("Java开发", 79.5);
        Book bkB = new Book("JSP", 45.6);
        System.out.println(bkA.getInfo()); // 清华大学出版社
        System.out.println(bkB.getInfo()); // 清华大学出版社
        bkB.pub = "北京大学出版社";
        System.out.println(bkA.getInfo()); // 北京大学出版社
        System.out.println(bkB.getInfo()); // 北京大学出版社
    }
}

使用static定义属性后,只要有一个对象修改属性值,那么所有对象的该属性值都会改变,内存分析如下:
在这里插入图片描述
2. static定义的属性与普通属性区别在于保存数据的内存区域不同。
static定义的是公共属性,任由某个对象直接修改属性值是不合理的,应该由所有对象的代表进行属性访问,即用类访问。因此static定义的属性,可直接用类名调用:Book.pub = "北京大学出版社";
3. static属性与普通属性的区别在于:普通属性必须由实例化的对象调用,而在没有实例化对象的情况下,static属性依然可以被调用。

public class Demo {
    public static void main(String[] args) {
        // 没有实例化对象的情况下,输出pub的内容
        System.out.println(Book.pub);
    }
}

由结果可知:static虽然定义在类中,但不受对象控制,是独立于类存在的。
4. 何时使用static定义属性
编写类时,static不是首选修饰符,当需要描述共享信息时,才使用static,方便集体修改,不用重复开辟内存空间。

static 定义方法

1.static定义的方法也可以直接被类名调用

class Book {
    private String title;
    private double price;
    // 为操作方便,暂不封装
    private static String pub = "清华大学出版社";

    public Book(String title, double price) {
        this.title = title;
        this.price = price;
    }

    public static void setPub(String p){
        pub = p;
    }
    public String getInfo(){
        return "书名:" + this.title + ",价格:" + this.price + ",出版社:" + this.pub;
    }
}

public class Demo {
    public static void main(String[] args) {
        // 没有实例化对象的情况下,调用方法
        Book.setPub("北京大学出版社");
        Book bkA = new Book("Java开发", 79.5);
        System.out.println(bkA.getInfo()); // 北京大学出版社
    }
}

上述代码存在问题:类中有两种方法,static方法和普通方法,两种方法间的访问受到限制。
(1)static方法不能直接使用非static属性或方法,只能调用static属性或方法。

public static void setPub(String p){
   pub = p;
   title = "sss"; // 报错,无法引用非静态变量
   getInfo(); // 报错,无法引用非静态方法
   System.out.println(this); // 报错,无法引用非静态变量
}

(2)普通方法可以使用static属性或方法

public String getInfo(){
    setPub(""); // 不报错
    return ",出版社:" + this.pub; // 不报错
}

出现上述限制的原因:

|- 普通属性和方法必须在对象实例化后分配了堆内存空间,才可以使用;
|- static定义的方法和属性,不受实例化对象控制,可在没有实例化对象情况下访问。

2.一个方法定义在主类中,并由主方法直接调用,该方法定义格式如下:

public static 返回值类型 方法名(参数类型 参数, 参数类型 参数,...) {
    方法体; 
    [return [返回值] ;] // []中内容可写可不写
}

一个方法定义在类中,由对象直接调用,其语法格式如下:

public 返回值类型 方法名(参数类型 参数, 参数类型 参数,...) {
    方法体; 
    [return [返回值] ;] // []中内容可写可不写
}

观察代码:

public class Demo {
    public static void main(String[] args) {
        fun();
    }

    public static void fun() {
        System.out.println("Hello World !");
    }
}

没有static定义的fun()必须通过对象调用,主方法要使用fun()必须实例化对象

public class Demo {
    public static void main(String[] args) {
        // 产生对象,再利用对象调用非static方法
        new Demo().fun();
    }

    public void fun() {
        System.out.println("Hello World !");
    }
}
  1. 定义类中方法时,static不是首选修饰符,因为每个对象可以利用自己的属性实现方法的不同调用。
class Flag {
    private boolean flag;

    public Flag(boolean flag) {
        this.flag = flag;
    }

    public void fun() {
        if (this.flag) {
            System.out.println("可以操作");
        } else {
            System.out.println("不可以操作");
        }
    }
}

public class Demo {
    public static void main(String[] args) {
        Flag fA = new Flag(true);
        Flag fB = new Flag(false);
        fA.fun();
        fB.fun();
    }
}

当一个类中没有属性,只有方法时,建议将所有方法定义为static方法。这样就不用每次调用时都需要有实例化对象。

class MyMath {
    public static int add(int x, int y) {
        return x + y;
    }
}

public class Demo {
    public static void main(String[] args) {
        System.out.println(MyMath.add(10, 20));
    }
}

主方法

1.主方法的组成:

组成作用
public主方法是程序的开始,所以主方法必须是可见、public(公共的)的
static证明此方法可直接由类名调用
void主方法是程序的开始,因此不能回头,执行完为止,所以不能有返回值
main系统规定好的方法名,不能修改
String [] args指的是程序运行时传递的参数

范例:对主方法传入参数

public class Demo {
    public static void main(String[] args) {
        for (int x = 0; x < args.length ; x++) {
            System.out.println(args[x]); // 未输出参数,为空
        }
    }
}

多个参数时,必须使用空格分割。cmd执行的是java Demo 1 3 4 6
输出为:1 3 4 6
如果参数本身带有空格,需用""描述
cmd执行的是java Demo "Hello world" "Hello Java"

static应用案例

已知:
(1)多个对象,都使用同一个static属性;
(2)static定义方法可以避免实例化对象调用方法的限制。

1.实现对实例化对象个数的统计

要求:每实例化一个对象,就输出"这是第x个实例化对象"
思路:每次实例化对象,就会调用构造方法,因此可在构造方法中增加一个统计数据的操作,每当新对象产生,该属性值就自增加一。

class Book {
    private static int num = 0;

    public Book() {
        num++;
        System.out.println("这是第" + num + "个实例化对象");
    }
}

public class Demo {
    public static void main(String[] args) {
        new Book();
        new Book();
        new Book();
    }
}

2.实现属性的自动设置

要求:类中有一个无参构造方法,一个有参构造方法,有参构造方法的功能是传递title值。不论调用的哪个构造方法,均可为title赋值,且属性值尽量不重复。

class Book {
    private String title;
    private static int num = 0;

    public Book() {
        this("Title:No." + num++);
    }
    public Book(String title){
        this.title = title;
    }
    public String getTitle(){
        return  this.title;
    }
}

public class Demo {
    public static void main(String[] args) {
        System.out.println(new Book("Java开发").getTitle()); // Java开发
        System.out.println(new Book().getTitle()); // Title:No.0
        System.out.println(new Book().getTitle()); // Title:No.1
    }
}

总结
(1)类定义属性或方法首时选不是static属性或方法;
(2)static属性或方法可直接用类名调用;
(3)static属性保存在全局数据区。
(4)内存区有四种: 栈内存(对象的地址),堆内存(普通属性),全局数据区(static属性),全局代码区(所有的方法)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会画画的画师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值