文档章节

Java中static关键字的作用

此鱼不得水
 此鱼不得水
发布于 2016/04/11 10:57
字数 1623
阅读 103
收藏 0

我们经常在Java中使用static关键字,那么这么关键字究竟有哪些用途呢?我们一一道来。

1.用static修饰变量与方法

public class Main{
    private static Object;
    public static void fun(){
        System.out.println("Test Static");
    }

}

从以上代码中我们就见到static的最基本用法,也就是修饰变量和方法。那么我们肯定有疑惑,这个static关键字修饰后与普通的变量就什么不同的呢?

Static关键字代表依赖的对象是Main.class这个对象,而普通的没有static修饰的方法或者变量则依赖的是new Main()后生成的对象,所以从本质上来说两者的依赖是不一样的。

我们经常遇到的问题是在static 方法里面不能直接调用非static的变量以及方法,而在普通方法里面却可以调用static方法,为何呢?

这就跟类的加载顺序有一定的关系了,首先你在static方法里面调用非static方法/变量的话是不行的,因为有static修饰的方法会在类的初始化阶段就完成了,这个时候非static方法/变量还没有进行赋值,也就是说static修饰的方法先于非static修饰的方法完成,这样显然快的是没有办法依赖慢的喽。。但是你反过来调用确实可以的,道理我相信已经不用我在描述了。

2.用static修饰代码快

public class Main{
    static{
        System.out.println("static修饰代码快");
    }
}

这种用法也是比较常见的用法,用static修饰的代码块只会在类进行初始化的时候调用一次!,而非static修饰的代码块则是在每次生成对象的时候都进行一次调用。原理我还是在简单说一下,因为用static修饰的代码块与Main.class所绑定,而Main.class的类信息只会加载一次的,存储在方法区里面(JDK1.8以前),所以static块也只是在加载Main.class的时候进行一次运行过程;而非static的代码块就跟随这新生成的对象来调用,new一个对象就自己调用一次。

3.用static修饰静态内部类

如果你不需要内部类对象与其外围类对象之间有联系,那你可以将内部类声明为static。这通常称为嵌套类(nested class)。Static Nested Class是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。而通常的内部类需要在外部类实例化后才能实例化。想要理解static应用于内部类时的含义,你就必须记住,普通的内部类对象隐含地保存了一个引用,指向创建它的外围类对象。然而,当内部类是static的时,就不是这样了。嵌套类意味着: 

1. 嵌套类的对象,并不需要其外围类的对象。 

2. 不能从嵌套类的对象中访问非静态的外围类对象。 

如下所示代码为定义一个静态嵌套类

public class StaticTest{
   private static String name = "woobo";
   private String num = "X001";
   static class Person{ // 静态内部类可以用public,protected,private修饰 
       // 静态内部类中可以定义静态或者非静态的成员  
     private String address = "China";
Private Static String x=“as”;
     public String mail = "kongbowoo@yahoo.com.cn";//内部类公有成员
     public void display(){
       //System.out.println(num);//不能直接访问外部类的非静态成员
// 静态内部类不能访问外部类的非静态成员(包括非静态变量和非静态方法)
       System.out.println(name);//只能直接访问外部类的静态成员
//静态内部类只能访问外部类的静态成员(包括静态变量和静态方法)
       System.out.println("Inner " + address);//访问本内部类成员。
     }
   }
   public void printInfo(){
     Person person = new Person();
// 外部类访问内部类的非静态成员:实例化内部类即可 
person.display();
     //System.out.println(mail);//不可访问
     //System.out.println(address);//不可访问
     System.out.println(person.address);//可以访问内部类的私有成员
System.out.println(Person.x);// 外部类访问内部类的静态成员:内部类.静态成员
     System.out.println(person.mail);//可以访问内部类的公有成员
   }
   public static void main(String[] args){
     StaticTest staticTest = new StaticTest();
     staticTest.printInfo();
   }
}

在静态嵌套类内部, 不能访问外部类的非静态成员, 这是由Java语法中"静态方法不能直接访问非静态成员"所限定.注意, 外部类访问内部类的的成员有些特别, 不能直接访问, 但可以通过内部类实例来访问, 这是因为静态嵌套内的所有成员和方法默认为静态的了.同时注意, 内部静态类Person只在类StaticTest 范围内可见, 若在其它类中引用或初始化, 均是错误的.
一 . 静态内部类可以有静态成员,而非静态内部类则不能有静态成员。 
二 . 静态内部类的非静态成员可以访问外部类的静态变量,而不可访问外部类的非静态变量;

三 . 非静态内部类的非静态成员可以访问外部类的非静态变量。

    生成一个静态内部类不需要外部类成员:这是静态内部类和成员内部类的区别。静态内部类的对象可以直接生成:Outer.Inner in = new Outer.Inner();而不需要通过生成外部类对象来生成。这样实际上使静态内部类成为了一个顶级类(正常情况下,你不能在接口内部放置任何代码,但嵌套类可以作为接口的一部分,因为它是static 的。只是将嵌套类置于接口的命名空间内,这并不违反接口的规则)

4.用static来静态导包(JDK1.5之后)

public class Util{
    public static obj=new Object();
    public static void fun(){
        System.out.println("测试静态导包");
    }
}
------------------------------------------------------
import static Util.obj;
import static Util.fun;
public class Main{
    public static void main(String[] args){
        Object o=obj;
        fun();
    }
}

以上简单的代码中我们可以看到静态导包的好处了,就是可以省略一部分前缀,但是我们的日常使用中并不常见这种用法,主要是因为这种导包方式可能在包的数量比较多的时候会引起一定的混乱,导致代码不易阅读。


static的作用主要就是以上四种了。


© 著作权归作者所有

共有 人打赏支持
此鱼不得水
粉丝 2
博文 41
码字总数 23991
作品 0
洛阳
java 同步块(Java Synchronized Blocks)

Java 同步块包括方法同步和代码块同步。java 同步可以避免资源竞争,避免死锁。 主题包括的主要内容: 关键字 Synchronized 实例方法 Synchronized static methods Synchronized blocks in i...

丁佳辉
2015/08/18
0
0
java基础一(第一个java程序、数据类型、访问控制、static、)

一、第一个java程序 public class HelloWord {//public访问修饰符 class关键字,声明为类 HelloWord类名 //public访问修饰符 static关键字 void表示无返回值 main程序入口 } 二、数据类型 Ja...

废柴
02/11
0
0
java并发编程(2)——wait和notify解析

JAVA的进程同步是通过synchronized()来实现的,需要说明的是,JAVA的synchronized()方法类似于操作系统概念中的互斥内存块,在JAVA中的Object类型中,都是带有一个内存锁的,在有线程获取该内...

十二缸帕萨特
2014/04/12
0
0
Java并发学习之Volatile及内存模型探究

volatile工作原理 java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致的更新,线程应该确保通过排他锁单独获得这个变量。 Java语言提供了volatile,在某些情况下比锁更加方便...

小灰灰Blog
2017/11/02
0
0
简单的入门Android开发和Java语言基础[图]

简单的入门Android开发和Java语言基础[图] 前言: 去年年底到今年年初,我做过简单的智能家居,也实现过一些简单的直连和远程的智能家居。于是就将最简单的通信发布出来:智能家居简单实现—...

原创小博客
08/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

day92-20180918-英语流利阅读-待学习

健身最大的敌人不是懒惰,而是逞强 Daniel 2018-09-19 1.今日导读 还记得 2008 年北京奥运会运动员刘翔的退赛风波吗?那天几乎所有中国人都将视线聚焦在了鸟巢体育馆 110 米栏的项目上,迫不...

飞鱼说编程
32分钟前
2
0
70.shell的函数 数组 告警系统需求分析

20.16/20.17 shell中的函数 20.18 shell中的数组 20.19 告警系统需求分析 20.16/20.17 shell中的函数: ~1. 函数就是把一段代码整理到了一个小单元中,并给这个小单元起一个名字,当用到这段...

王鑫linux
今天
3
0
分布式框架spring-session实现session一致性使用问题

前言:项目中使用到spring-session来缓存用户信息,保证服务之间session一致性,但是获取session信息为什么不能再服务层获取? 一、spring-session实现session一致性方式 用户每一次请求都会...

WALK_MAN
今天
6
0
C++ yield()与sleep_for()

C++11 标准库提供了yield()和sleep_for()两个方法。 (1)std::this_thread::yield(): 线程调用该方法时,主动让出CPU,并且不参与CPU的本次调度,从而让其他线程有机会运行。在后续的调度周...

yepanl
今天
4
0
Java并发编程实战(chapter_3)(线程池ThreadPoolExecutor源码分析)

这个系列一直没再写,很多原因,中间经历了换工作,熟悉项目,熟悉新团队等等一系列的事情。并发课题对于Java来说是一个又重要又难的一大块,除非气定神闲、精力满满,否则我本身是不敢随便写...

心中的理想乡
今天
59
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部