Java基础(二)-static关键字分析
一、前言
static关键字是我们在编程中经常会使用到的,但有些可能只知其然而不知其所以然。下面介绍static关键字的作用再通过例子结合说明。
static关键字共有五种作用(先说明static所修饰的不会改变其(private、protected、default和public)作用域的范围):
- 修饰成员变量(非局部变量)
- 修饰成员方法
- 修饰代码块
- 修饰内部类
- 静态导包
怎么会有五种呢,大部分初学者对前面两种或者加上第三种还是很熟悉的,第四种情况可能一开始的人就比较少知道了,第五种就更少人知道了。下面一一介绍:
二、修饰成员变量
- 说明及特点:static所修饰的变量也叫做静态变量,该变量在类初次加载时会被初始化,所以它在内存中只有一个副本,被所有对象所共享(前提也是public所修饰的),其实也叫做类变量,直接通过类可以调用。而非静态变量是在创建对象的时候被初始化,存在多个副本但各个副本互不影响,它也叫做实例化对象的变量。其中要注意的是static不能修饰局部变量(定义在函数内,语句内等,只在所属的区域有效)
- 好处:优先加载、内存利用率高(类初始化时加载且仅分配一次内存); 调用简单
- 案例解析:
package com.yuanfy.test.statics;
class Student {
//非静态变量
private String name;
int age;
//静态变量、全局变量
public static String schoolName = "清华大学";
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void say(){
static int count = 0;//编译报错,不能定义局部变量
}
public String getName() {
return name;
}
}
public class StaticTest {
public static void main(String[] args) {
Student s1 = new Student("张三", 18);
//1、只能通过实例对象调用
System.out.println("name: " + s1.getName() + ", age: " + s1.age);
//2、可以通过类直接调用,如果schoolName是public在其他包下也是可以直接通过类调用的,这样的变量也叫做全局变量
System.out.println("school:" + Student.schoolName);
//3、非静态变量只属于实例对象,所以对应成员变量的值互不影响。
Student s2 = new Student("李四", 19);
System.out.println("测试非静态变量是否会影响其他实例对象下的使用:");
System.out.println("name: " + s1.getName() + ", age: " + s1.age);//name: 张三, age: 18
System.out.println("name: " + s2.getName() + ", age: " + s2.age);//name: 李四, age: 19
//静态变量会影响使用。
System.out.println("静态变量会影响使用:");
s2.schoolName = "北京大学";
System.out.println("s2 school:" + s1.schoolName);//s1的学校名称肯定会改变成s2的学校名
}
}
output:
name: 张三, age: 18
school:清华大学
测试非静态变量是否会影响其他实例对象下的使用:
name: 张三, age: 18
name: 李四, age: 19
静态变量会影响使用:
s2 school:北京大学
三、修饰成员方法
- 说明:static所修饰的方法叫做静态方法,也称类方法。
- 特点:
1、跟静态变量一样,静态方法属于类而不属于对象,所以静态方法可以通过类直接调用,而不需要创建对象实例来调用。
2、由于静态方法是通过类直接调用的,所以静态方法中没有this对象。
3、静态方法可以调用静态变量或方法,但是不能调用非静态变量或方法
4、静态方法不能被覆盖。因为静态方法是编译时静态绑定的,而覆盖是基于运行时动态绑定的。
注意:构造方法不是静态方法,可以参考这里。
- 案例解析:
class Student {
//非静态变量
private String name;
int age;
//静态变量、全局变量
public static String schoolName = "清华大学";
public Student(){}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public static void say(){
//2、由于静态方法是通过类直接调用的,所以静态方法中没有this对象。
System.out.println("调用者:" + this);//编译失败
//3、静态方法可以调用静态变量或方法,但是不能调用非静态变量或方法
//Cannot make a static reference to the non-static
System.out.println("调用非静态变量name:" + name);//编译失败
//但是可以调用静态方法
System.out.println("调用静态变量schoolName:" + schoolName);
}
public void setName(){
//非静态方法可以使用this,知道是哪个实例对象在调用。
System.out.println("调用者:" + this);
}
}
class StudentDTO extends Student{
//编译报错; 4、静态方法不能被覆盖覆盖。因为静态方法是编译时静态绑定的,而覆盖是基于运行时动态绑定的。
31 @Override
32 public static void say(){
33
34 }
}
四、修饰代码块
- 说明:static修饰在代码块前用来形成静态代码块以优化程序性能。
- 特点:
1、在类初次被加载的时候在加载,只加载一次;
2、一个类可以有多个代码块,按代码块的顺序执行。
- 案例分析:
public class StaticTest {
static {
System.out.println("第一次加载静态代码块内容");
}
public static void main(String[] args) {
//不需要实例化对象,只要类加载就会执行static块内容。
// 与执行顺序与代码块的顺序一致。
}
static {
System.out.println("第二次加载静态代码块内容");
}
}
output:
第一次加载静态代码块内容
第二次加载静态代码块内容
五、修饰内部类
- 说明:static修饰的内部类成为静态内部类。
- 特点:
1、普通类不可以用static修饰,只有内部类才可以。(语法)
2、非静态内部类无法声明静态方法和静态变量,只有静态内部类才可以。原因很简单:当加载该类时,会自动解析类中static所修饰的所有变量、方法、代码块和内部类,而静态变量定义在非静态内部类,所以不会加载。而jvm虚拟机是要求静态变量必须是在类加载时初始化的。所以会编译报错,无法声明。
3、非静态内部类可以随意访问外部类的成员或方法,而静态内部类只能访问静态变量或方法。
4、调用静态内部类不需要持有外部内的引用可以直接调用,而非静态内部类就必须持有外部内的引用才能调用
- 案例分析:
public class StaticTest {
private static int startPrice = 10;//起步价
private static int kmPrice = 2;//每一公里2块钱
private int kmCount;//里程计时器
static class Car1{
//编译成功, 2、非静态内部类无法声明静态方法和静态变量,只有静态内部类才可以。
public static void start(){
11 //编译失败,3、非静态内部类可以随意访问外部类的成员或方法,而静态内部类只能访问静态变量或方法。
12 // kmCount = 0;
System.out.println("car1汽车启动,起步价是:" + startPrice);
}
}
class Car2{
17 //编译报错。 2、非静态内部类无法声明静态方法和静态变量,只有静态内部类才可以。
18 // public static void start(){
19 // System.out.println("开始启动");
20 // }
public void start2(){
//编译成功,3、非静态内部类可以随意访问外部类的成员或方法,而静态内部类只能访问静态变量或方法。
kmCount = 0;
System.out.println("car2汽车启动,起步价是:" + startPrice);
}
}
public static void main(String[] args) {
StaticTest.Car1.start();
30 //编译报错 4、调用静态内部类不需要持有外部内的引用可以直接调用,而非静态内部类就必须持有外部内的引用才能调用
31 // StaticTest.Car2.start();
//编译成功
StaticTest.Car2 car2 = new StaticTest().new Car2();
car2.start2();
}
}
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所修饰加载的先后顺序):静态代码块和静态变量无优先顺序,只跟其定义的前后顺序有关;静态代码块和变量优先静态方法。
class Test{
public Test(){
System.out.println("test()");
}
}
public class StaticTest3 {
static {
System.out.println("代码块1");
}
private static Test test = new Test();
static {
System.out.println("代码块2");
}
public static void test(){
System.out.println("StaticTest3 test()");
}
public static void main(String[] args) {
StaticTest3.test();
}
}
output:
代码块1
test()
代码块2
StaticTest3 test()
本篇文章分析到此结束,参考文献如下:
http://rednaxelafx.iteye.com/blog/652719
https://www.cnblogs.com/dolphin0520/p/3799052.html
Java基础(二)-static关键字分析的更多相关文章
- Java基础之static关键字的用法
Java中的static关键字主要用于内存管理.我们可以应用static关键字在变量.方法.块和嵌套类中. static关键字属于类,而不是类的实例. 静态(static)可以是: 变量 ...
- Java基础系列--static关键字
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/8477914.html 一.概述 static关键字是Java诸多关键字中较常使用的一个,从 ...
- Java基础(三)-final关键字分析
今天来谈谈final关键字的作用, 虽然有很多博文关于final进行了很深的研究,但还是要去记录下谈谈自己的见解加深下印象.下面直接进入主题: 一.final关键字的作用 1.被final修饰的类不能 ...
- 【Java基础】static关键字相关
static关键字特点: 随着类的加载而加载. 优先于对象存在. 被所有对象共享 可以直接被类名调用. 使用注意: 静态方法只能访问静态成员. 但非静态成员可以访问静态成员. 静态方法中不能使用thi ...
- Java基础(十)--static关键字
static关键字通常应用在字段.方法.静态块,还有冷门一点的内容:静态内部类.静态导入 static字段: static字段也就是静态变量,是属于类的,被所有的对象所共享,只有当类初次加载的时候保存 ...
- java基础 2 static关键字
2. static关键字 变量:静态变量在内存中只存在一份,只在类第一次实例化时初始化一次,同时类所有的实例都共享静态变量,可以直接同过类名 来访问他. 方法:静 ...
- Java基础(二)--this关键字及初始化
构造器: 构造器的名称必须和类名完全相同,所以一般方法的"首字母小写"命名规则并不适合构造器 默认构造器: 也叫无参构造器,作用就是创建一个默认对象,如果你不是手写出来,编译器默认 ...
- 【Java基础】static关键字的理解
修饰范围: 可以修饰成员变量和成员方法.静态的特点: A:随着类的加载而加载 B:优先于对象存在 C:被类的所有对象共享 这其实也是我们判断该不该使用静态的依据. 举例:饮水机和水杯的问题思考可通过类 ...
- 094 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 02 static关键字 04 static关键字(续)
094 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 ...
随机推荐
- Hadoop(十七)之MapReduce作业配置与Mapper和Reducer类
前言 前面一篇博文写的是Combiner优化MapReduce执行,也就是使用Combiner在map端执行减少reduce端的计算量. 一.作业的默认配置 MapReduce程序的默认配置 1)概述 ...
- zabbix3.2源码搭建
首先环境是标准的lnmp 1.创建zabbix组和系统用户来管理 groupadd zabbix useradd -g zabbix zabbix -s /sbin/nologin 2.在mysql ...
- IT连创业系列:说说苹果商店AppStore上架App应用前后遇到的那些神坑
前言: IT连创业的这个系列,又隔空了一个多月了. 不知道为什么,最近写文的冲动感下降了很多,如果不是因为特别忙,大概就因为上了年纪的原因了. 群里关注我创业的朋友,一直都在问,啥时候有新的文章讲述创 ...
- java中this关键字解析
由于this关键字在Java程序中经常见到,笔者索性把它的用法总结一下,来和大家一到互相学习一下.总的来说this用在下面几个地方: (1)当局部变量和成员变量同名的时候,需要用this来加以区分 如 ...
- HDU 6047 Maximum Sequence
Maximum Sequence Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- ldap数据库--ODSEE--复制协议
简单介绍一下ODSEE的复制拓扑的建立,复制协议可以通过管理界面进行创建,也可以通过命令行创建.在此之前需要了解一些复制协议的相关概念,这里针对OESEE. 1,复制角色 master(提供者,也可以 ...
- 一款非常推荐的用户界面插件----EasyUI
前 言 easyui是一种基于jQuery的用户界面插件集合. easyui为创建现代化,互动,JavaScript应用程序,提供必要的功能. 使用easyui你不需要写很多代码,你只需要 ...
- 表空间与数据文件Offline,online的区别
首先明确,表空间与数据文件的关系:Oracle数据库表空间有两种,一种smallfile小文件表空间(默认),另一种bigfile大文件表空间: 默认表空间与数据文件的关系:允许一对多的处理方式,一个 ...
- java面试题及答案
JAVA相关基础知识1.面向对象的特征有哪些方面 1.抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时 ...
- ThreeJS的特效合成器和后期处理通道
最近要写个 web 交互式发光可交互的框架.没查到啥好资料,自己一个人摸索了很久,有些失望,可是毕竟是探索过的东西,所以做个记录,怀念我过去好多天掉的青丝(捂脸).我在前面那篇博客里面已经介绍了如何让 ...