Java基础(二)-static关键字分析

static关键字是我们在编程中经常会使用到的,但有些可能只知其然而不知其所以然。下面介绍static关键字的作用再通过例子结合说明。

static关键字共有五种作用(先说明static所修饰的不会改变其(private、protected、default和public)作用域的范围):
  修饰成员变量(非局部变量)
  修饰成员方法
  修饰代码块
  修饰内部类
  静态导包

怎么会有五种呢,大部分初学者对前面两种或者加上第三种还是很熟悉的,第四种情况可能一开始的人就比较少知道了,第五种就更少人知道了。下面一一介绍:

一、修饰成员变量

  说明及特点:static所修饰的变量也叫做静态变量,该变量在类初次加载时会被初始化,所以它在内存中只有一个副本,被所有对象所共享(前提也是public所修饰的),其实也叫做类变量,直接通过类可以调用。而非静态变量是在创建对象的时候被初始化,存在多个副本但各个副本互不影响,它也叫做实例化对象的变量。其中要注意的是static不能修饰局部变量(定义在函数内,语句内等,只在所属的区域有效)

  好处:优先加载、内存利用率高(类初始化时加载且仅分配一次内存);  调用简单

  案例解析:

 1 package com.yuanfy.test.statics;
 2
 3 class Student {
 4     //非静态变量
 5     private String name;
 6     int age;
 7     //静态变量、全局变量
 8     public static String schoolName = "清华大学";
 9
10     public Student(String name, int age) {
11         this.name = name;
12         this.age = age;
13     }
14
15     public void say(){
16         static int count = 0;//编译报错,不能定义局部变量
17     }
18
19     public String getName() {
20         return name;
21     }
22
23 }
24 public class StaticTest {
25     public static void main(String[] args) {
26         Student s1 = new Student("张三", 18);
27         //1、只能通过实例对象调用
28         System.out.println("name: " + s1.getName() + ", age: " + s1.age);
29         //2、可以通过类直接调用,如果schoolName是public在其他包下也是可以直接通过类调用的,这样的变量也叫做全局变量
30         System.out.println("school:" + Student.schoolName);
31
32         //3、非静态变量只属于实例对象,所以对应成员变量的值互不影响。
33         Student s2 = new Student("李四", 19);
34         System.out.println("测试非静态变量是否会影响其他实例对象下的使用:");
35         System.out.println("name: " + s1.getName() + ", age: " + s1.age);//name: 张三, age: 18
36         System.out.println("name: " + s2.getName() + ", age: " + s2.age);//name: 李四, age: 19
37
38         //静态变量会影响使用。
39         System.out.println("静态变量会影响使用:");
40         s2.schoolName = "北京大学";
41         System.out.println("s2 school:" + s1.schoolName);//s1的学校名称肯定会改变成s2的学校名
42     }
43 }

output:

name: 张三, age: 18
school:清华大学
测试非静态变量是否会影响其他实例对象下的使用:
name: 张三, age: 18
name: 李四, age: 19
静态变量会影响使用:
s2 school:北京大学

二、修饰成员方法

  说明:static所修饰的方法叫做静态方法,也称类方法。

  特点:

  1、跟静态变量一样,静态方法属于类而不属于对象,所以静态方法可以通过类直接调用,而不需要创建对象实例来调用。
  2、由于静态方法是通过类直接调用的,所以静态方法中没有this对象。
  3、静态方法可以调用静态变量或方法,但是不能调用非静态变量或方法
  4、静态方法不能被覆盖。因为静态方法是编译时静态绑定的,而覆盖是基于运行时动态绑定的。

  注意:构造方法不是静态方法,可以参考这里

  案例解析:

 1 class Student {
 2     //非静态变量
 3     private String name;
 4     int age;
 5     //静态变量、全局变量
 6     public static String schoolName = "清华大学";
 7
 8     public Student(){}
 9     public Student(String name, int age) {
10         this.name = name;
11         this.age = age;
12     }
13
14     public static void say(){
15         //2、由于静态方法是通过类直接调用的,所以静态方法中没有this对象。
16         System.out.println("调用者:" + this);//编译失败
17         //3、静态方法可以调用静态变量或方法,但是不能调用非静态变量或方法
18         //Cannot make a static reference to the non-static
19         System.out.println("调用非静态变量name:" + name);//编译失败
20         //但是可以调用静态方法
21         System.out.println("调用静态变量schoolName:" + schoolName);
22     }
23     public void setName(){
24         //非静态方法可以使用this,知道是哪个实例对象在调用。
25         System.out.println("调用者:" + this);
26     }
27 }
28 class StudentDTO extends Student{
29
30     //编译报错; 4、静态方法不能被覆盖覆盖。因为静态方法是编译时静态绑定的,而覆盖是基于运行时动态绑定的。
31     @Override
32     public static void say(){
33
34     }
35
36 }

三、修饰代码块

  说明:static修饰在代码块前用来形成静态代码块以优化程序性能。

  特点:

  1、在类初次被加载的时候在加载,只加载一次;

  2、一个类可以有多个代码块,按代码块的顺序执行。

  案例分析:

 1 public class StaticTest {
 2     static {
 3         System.out.println("第一次加载静态代码块内容");
 4     }
 5
 6     public static void main(String[] args) {
 7         //不需要实例化对象,只要类加载就会执行static块内容。
 8         // 与执行顺序与代码块的顺序一致。
 9     }
10
11     static {
12         System.out.println("第二次加载静态代码块内容");
13     }
14 }    

output:

第一次加载静态代码块内容
第二次加载静态代码块内容

四、修饰内部类

  说明:static修饰的内部类成为静态内部类。

  特点:

  1、普通类不可以用static修饰,只有内部类才可以。(语法)

  2、非静态内部类无法声明静态方法和静态变量,只有静态内部类才可以。原因很简单:当加载该类时,会自动解析类中static所修饰的所有变量、方法、代码块和内部类,而静态变量定义在非静态内部类,所以不会加载。而jvm虚拟机是要求静态变量必须是在类加载时初始化的。所以会编译报错,无法声明。

  3、非静态内部类可以随意访问外部类的成员或方法,而静态内部类只能访问静态变量或方法。

  4、调用静态内部类不需要持有外部内的引用可以直接调用,而非静态内部类就必须持有外部内的引用才能调用

  案例分析:

 1 public class StaticTest {
 2     private static int startPrice = 10;//起步价
 3
 4     private static int kmPrice = 2;//每一公里2块钱
 5
 6     private int kmCount;//里程计时器
 7
 8     static class Car1{
 9         //编译成功, 2、非静态内部类无法声明静态方法和静态变量,只有静态内部类才可以。
10         public static void start(){
11             //编译失败,3、非静态内部类可以随意访问外部类的成员或方法,而静态内部类只能访问静态变量或方法。
12 //            kmCount = 0;
13             System.out.println("car1汽车启动,起步价是:" + startPrice);
14         }
15     }
16     class Car2{
17         //编译报错。 2、非静态内部类无法声明静态方法和静态变量,只有静态内部类才可以。
18 //        public static void start(){
19 //            System.out.println("开始启动");
20 //        }
21
22         public void start2(){
23             //编译成功,3、非静态内部类可以随意访问外部类的成员或方法,而静态内部类只能访问静态变量或方法。
24             kmCount = 0;
25             System.out.println("car2汽车启动,起步价是:" + startPrice);
26         }
27     }
28     public static void main(String[] args) {
29         StaticTest.Car1.start();
30         //编译报错 4、调用静态内部类不需要持有外部内的引用可以直接调用,而非静态内部类就必须持有外部内的引用才能调用
31 //        StaticTest.Car2.start();
32
33         //编译成功
34         StaticTest.Car2 car2 = new StaticTest().new Car2();
35         car2.start2();
36     }
37 }

output:

car1汽车启动,起步价是:10
car2汽车启动,起步价是:10

五、静态导包

  说明:其实很简单,跟平常导包差不多,只是在import后面加上static,然后再在类后面引入所有成员(变量、方法、内部类等)用.*代替。格式如下:import static classPath.*;这个不是很常用,也不建议使用,请看下面特点及不足之处。

  特点:

  对于导入静态包可以直接使用其静态方法。

  不足之处:

  1、代码不直观:如果导入了多个静态包,不仔细看是不知道这个方法来源于哪个类 。

  2、会存在方法冲突。

  案列分析1:

package com.yuanfy.test;
/**
 * @description 字符串工具类案例
 * @author YuanFY
 * @date 2017年12月10日 上午11:35:25
 * @version 1.0
 */
public class StringUtil {
    public static boolean isEmpty(String str){
        return true;
    }
}
package com.yuanfy.test.statics;
//导入静态包
import static com.yuanfy.test.StringUtil.*;
//import static com.yuanfy.test.scope2.StringUtil.*;
public class StaticTest2 {

    public static void main(String[] args) {
        String str1 = "123";
        String str2 = new String("123");
        //方便之处直接使用静态方法,不直观
        if (isEmpty(str1)){

        }
    }
}

  案列分析2(导入多个静态包):

package com.yuanfy.test.scope2;
//注意这是不同包下的工具类
public class StringUtil {
    public static boolean isEmpty(String str){
        return true;
    }
}
package com.yuanfy.test.statics;
//导入多个静态包
import static com.yuanfy.test.StringUtil.*;
import static com.yuanfy.test.scope2.StringUtil.*;
public class StaticTest2 {

    public static void main(String[] args) {
        String str1 = "123";
        String str2 = new String("123");
        //编译报错,The method isEmpty(String) is ambiguous for the type StaticTest2
        if (isEmpty(str1)){

        }
    }
}

拓展(static所修饰加载的先后顺序):静态代码块和静态变量无优先顺序,只跟其定义的前后顺序有关;静态代码块和变量优先静态方法。

 1 class Test{
 2     public Test(){
 3         System.out.println("test()");
 4     }
 5 }
 6 public class StaticTest3 {
 7     static {
 8         System.out.println("代码块1");
 9     }
10     private static Test test = new Test();
11     static {
12         System.out.println("代码块2");
13     }
14
15     public static void test(){
16         System.out.println("StaticTest3 test()");
17     }
18
19     public static void main(String[] args) {
20         StaticTest3.test();
21     }
22 }

output:

代码块1
test()
代码块2
StaticTest3 test()

本篇文章分析到此结束,参考文献如下:

http://rednaxelafx.iteye.com/blog/652719

https://www.cnblogs.com/dolphin0520/p/3799052.html

时间: 2024-10-11 00:37:28

Java基础(二)-static关键字分析的相关文章

Java基础之static关键字的用法

Java中的static关键字主要用于内存管理.我们可以应用static关键字在变量.方法.块和嵌套类中. static关键字属于类,而不是类的实例.        静态(static)可以是: 变量(也称为类变量) 方法(也称为类方法) 代码块 嵌套类         修饰变量 被static修饰的变量称作静态变量或类变量:没有被static修饰的变量,称为实例变量.静态变量在内存中只有一个拷贝(节省内存),JVM只为静态变量分配一次内存,在类加载的过程中完成静态变量的内存分配(存储在"方法区

Java基础(三)-final关键字分析

今天来谈谈final关键字的作用, 虽然有很多博文关于final进行了很深的研究,但还是要去记录下谈谈自己的见解加深下印象.下面直接进入主题: 一.final关键字的作用 1.被final修饰的类不能被继承. 这一点应该很多人都知道也遇到过,经典案例就是java.lang.String类 还有一些常见的类也是被final所修饰的,如下: 基本类型对应的包装类型(如java.lang.Integer.java.lang.Long等).字符相关类(java.lang.StringBuilder.ja

Java基础之static关键字

static方法就是没有this的方法.在static方法内部不能调用非静态方法,反过来是可以的.而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法.这实际上正是static方法的主要用途.static可以用来修饰类的成员方法.类的成员变量,另外可以编写static代码块来优化程序性能.但是在Java中切记:static是不允许用来修饰局部变量. static方法 static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有th

一、Java基础之static关键字

static关键字可以用来修饰变量.方法.代码块以及内部类. 静态资源从JVM的类加载机制角度来说,它是在类首次被初始化时加载到方法区,而非静态资源需要类new出对象的时候被加载到堆栈里.如:使用Class.forName("xxx")方法初始化某个类来加载静态资源,同样的,在new出对象前会确保该类被初始化了. static变量: 静态变量被所有对象共享,在内存中只有一份.故,被任意对象修改该静态变量后,会影响到所有对象. (PS:在多线程中需要多注意共享资源的使用.) static

【Java基础】static关键字相关

static关键字特点: 随着类的加载而加载. 优先于对象存在. 被所有对象共享 可以直接被类名调用. 使用注意: 静态方法只能访问静态成员. 但非静态成员可以访问静态成员. 静态方法中不能使用this,super关键字. 主方法(main)是静态的. 看了上面是不是想睡觉了,单纯的概念是挺烦人的,那下面让我们在实际代码中来加深对他们的认知. 方法的调用可以分为两种: 对象调用: 对象.方法(实参) 类调用: 这个方法所在类的名字.方法(实参)//前提是这个方法必须被static修饰. 没有使用

Java基础(十)--static关键字

static关键字通常应用在字段.方法.静态块,还有冷门一点的内容:静态内部类.静态导入 static字段: static字段也就是静态变量,是属于类的,被所有的对象所共享,只有当类初次加载的时候保存到内存中,在内存中只保存一份 实例变量是属于对象的,在创建对象的时候进行初始化,每个对象的实例变量是互斥的,不会相互影响 PS:static是不允许用来修饰局部变量,无论是方法.静态块.代码块 static方法: public class A{ private static int i = 1; p

【转载-Java基础】Java中的static关键字解析

[转载]Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键字的用法和平常容易误解的地方,最后列举了一些面试笔试中常见的关于static的考题.以下是本文的目录大纲: 一.static关键字的用途 二.static关键字的误区 三.常见的笔试面试题 若有不正之处,希望谅解并欢迎批评指正. 请尊重作者劳动成果,转载请标明原文链接:http://www.

Java基础语法(一)---关键字、常量、变量、运算符

Java基础语法(一)---关键字.常量.变量.运算符一.关键字 定义:被Java赋予了特殊含义的单词. 特点:体现上都是英文小写. 1. 用于定义数据类型的关键字 基本数据类型: 整数类型: byte(1字节,最大值127) short(2字节,最大值为2^15-1) int(4字节,最大值为2^31-1) long(8字节,最大值为2^63-1) 浮点类型: float (单精度实数在内存中占32bit 有效数字为6~7位) double(双精度实数占内存单元为64bit 有效数字为15~1

(转)Java中的static关键字解析

转载: http://www.cnblogs.com/dolphin0520/p/3799052.html 一.static关键字的用途 在<Java编程思想>P86页有这样一段话: "static方法就是没有this的方法.在static方法内部不能调用非静态方法,反过来是可以的.而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法.这实际上正是static方法的主要用途." 这段话虽然只是说明了static方法的特殊之处,但是可以看出static关键