Java 面向对象之 static 关键字
static 特点
- static 是一个修饰符, 用于修饰成员
- static 修饰的成员被所有的对象所共享
- static 优先于对象存在, 因为 static 的成员随着类的加载就已经存在了
- static 修饰的成员多了一种调用方式, 即可以直接被类名所调用, 类名.静态成员
- static 修饰的数据是共享数据, 对象中存储的是特有数据.
成员变量(实例变量)与静态变量(类变量) 的区别
- 两个变量的生命周期不同
成员变量随着对象的创建而存在, 随着对象的被回收而释放
静态变量随着类的加载而存在, 随着类的消失而消失 - 调用方式不同
成员变量只能被对象调用
静态变量可以被对象调用, 还可以被类名调用 - 别名不同
成员变量也称为实例变量
静态变量也称为类变量 - 数据存储位置不同
成员变量数据存储在堆内存的对象中, 所以也叫对象的特有数据
静态变量数据存储在方法区(共享数据区)的静态区, 所以也叫对象的共享数据
静态使用注意事项
- 静态方法只能访问静态成员(包括成员变量和成员函数), 非静态方法即可以访问静态成员, 也可以访问非静态成员.
- 静态方法中不可以使用 this 或者 super 关键字.
- 主函数是静态的, 所以只能访问静态方法和静态变量.
- 静态前面省略的是类名, 非静态前面省略的是 this
备注:- 主函数是静态的, 所以只能访问静态方法和静态变量.
public Demo
{
int num = 4;
public static void main(String[] args)
{
show();
}
public void show()
{
System.out.println(num);
}
}
// 编译失败, show() 方法和成员变量 num 都是非静态的.
// 改进
public Demo
{
int num = 4;
public static void main(String[] args)
{
new Demo().show(); // 使用对象调用 show() 方法
}
public void show()
{
System.out.println(num);
}
}
2. 静态前面省略的是类名, 非静态前面省略的是 this
class Person
{
public static void main(String[] args)
{
String name;
static String country = "CN";
public void show()
{
System.out.println(country+":"+name);
// 完整写法: System.out.println(Person.country+":"+this.name);
}
}
}
主函数解析
- 格式:
public static void main(String[] args)
- 主函数特殊之处
- 格式是固定的
- 被 JVM 所识别和调用
public: 因为权限必须是最大的;
static: 不需要对象, 直接用主函数所属类名调用即可
void: 主函数没有具体的返回值
main: 函数名, 不是关键字, 只是 JVM 识别的固定的名字
String[] args: 这是主函数的参数列表, 是一个数组类型的参数, 而且元素都是字符串类型
虚拟机调用主函数时, 传递了参数 new String[0].
static 内存图解
class Person
{
private String name;
private int age;
static String country = "CN";
public Person(String name, int age)
{
this.name = name;
this.age = age;
}
public void show()
{
System.out.println(Person.country+":"+this.name+":"+this.age);
}
public static void method()
{
System.out.println(Person.country);
}
}
class StaticDemo
{
public static void main(String[] args)
{
Person.method(); // 使用类名调用静态方法
Person p = new Person("旺财",20);
p.show();
}
}
静态什么时候使用?
- 静态变量
当分析对象中所具备的成员变量的值都是相同的, 这时这个成员就可以被静态修饰.
只有数据在对象中都是不同的, 那就是对象的特有数据, 必须存储在对象中, 是非静态的.
如果是相同的数据, 对象不需要作修改, 只需要使用即可, 不需要存储在对象中, 定义成静态的. - 静态函数
函数是否用静态修饰, 就参考一点, 就是该函数功能是否有访问到对象中的特有数据.
简单点说, 从源代码看, 该功能是否需要访问非静态的成员变量, 如果需要, 该功能就是非静态的.
如果不需要, 就可以将功能定义成静态的.当然, 也可以定义成非静态的.
但是非静态方法需要被对象调用, 而创建对象仅仅是为了调用非静态的, 非静态方法没有访问特有数据, 该对象的创建是没有意义的.
class Person
{
int age;
static String country = "CN";
public void speak()
{
System.out.println("haha");
}
}
class Demo
{
public static void main(String[] args)
{
Demo d = new Demo();
d.speak(); // 调用 speak() 方法需要创建对象, 但是 speak() 方法并没有访问特有数据, 对象的创建没有意义
}
}
// 改进
class Person
{
int age;
static String country = "CN";
public static void speak() // 将方法定义为静态的
{
System.out.println("haha");
}
}
class Demo
{
public static void main(String[] args)
{
Person.speak(); //使用类名调用该方法
}
}
静态代码块
特点: 随着类的加载而执行, 而且只执行一次.
作用: 用于给类进行初始化. 如果这个类的成员全是静态的, 并不需要创建对象.
public StaticCode
{
static // 静态代码块
{
System.out.println("haha");
}
void show()
{
System.out.println("show run");
}
}
class StaticCodeDemo
{
pulic static void main(String[] args)
{
new StaticCode().show();
}
}
构造代码块
定义: 定义在类中的代码块称为构造代码块
作用: 可以给所有对象初始化
构造函数: 是给对应的对象进行针对性的初始化.
局部代码块: 限定局部变量的生存周期. 定义在方法中.
执行顺序: 静态代码块先执行, 如果有对象, 执行构造代码块,再执行构造函数. 然后执行局部代码块
class Person
{
private String name;
Person()
{
name = "baby";
System.out.println("哇哇");
}
Person(String name)
{
this.name = name;
System.out.println("哇哇");
}
public void speak()
{
System.out.println("name:" + name);
}
}
class Demo
{
public static void main(String[] args)
{
Person p1 = new Person();
Person p2 = new Person("旺财");
p1.speak();
p2.speak();
}
}
// 改进
class Person
{
private String name;
// 类中的代码块称为构造代码块. 创建对象时,调用. 可以给所有对象进行初始化
{
System.out.println("person run");
}
Person()
{
name = "baby";
cry(); // 提高复用性
}
Person(String name)
{
this.name = name;
cry(); // 提高复用性
}
pulic void cry()
{
System.out.println("哇哇");
}
public void speak()
{
System.out.println("name:" + name);
}
}
class Demo
{
// 省略...
}
//再改进
class Person
{
private String name;
// 类中的代码块称为构造代码块. 创建对象时,调用. 可以给所有对象进行初始化
{
cry();
}
Person()
{
name = "baby";
}
Person(String name)
{
this.name = name;
}
pulic void cry()
{
System.out.println("哇哇");
}
public void speak()
{
System.out.println("name:" + name);
}
}
class Demo
{
// 省略...
}
_参考资料:_
- [JavaSE 基础视频(毕向东)](https://www.bilibili.com/video/av3092180/#page=1)
Java 面向对象之 static 关键字的更多相关文章
- 131、Java面向对象之static关键字三(使用static定义方法)
01.代码如下: package TIANPAN; class Book { // 描述的是同一个出版社的信息 private String title; private double price; ...
- 130、Java面向对象之static关键字二(在没有实例化对象产生时直接操作static属性)
01.代码如下: package TIANPAN; class Book { // 描述的是同一个出版社的信息 private String title; // 普通属性 private double ...
- 129、Java面向对象之static关键字一(修改static变量)
01.代码如下: package TIANPAN; class Book { // 描述的是同一个出版社的信息 private String title; // 普通属性 private double ...
- 132、Java面向对象之static关键字四(定义一个数学的加法操作)
01.代码如下: package TIANPAN; class MyMath { // 数学操作类,类中没有属性 public static int add(int x, int y) { // 只是 ...
- 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封装 ...
- 093 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 02 static关键字 03 static关键字(下)
093 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 ...
- 092 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 02 static关键字 02 static关键字(中)
092 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 ...
- 091 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 02 static关键字 01 static关键字(上)
091 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 ...
- Java面向对象-package import关键字
Java面向对象-package import关键字 package包关键字,在java中,有包的概念,主要是用来归类 分类作用: 便于项目的开发和维护: 这里截取随便截取一个我最近在开发的一个开源工 ...
随机推荐
- linux中的系统服务--daemon
简单的说,系统为了某些功能必须要提供一些服务 (不论是系统本身还是网络方面),这个服务就称为 service . 但是 service 的提供总是需要程序的运行吧!否则如何运行呢?所以达成这个 ser ...
- 调试JDK1.8源码的方法
背景 在学习JDK源码的时候,免不了需要调试JDK的源码. 比如:想理解ConcurrentHashMap的put(K k, V v)方法,JDK自带的rt.jar文件是支持断点调试,但是却看不到变量 ...
- C/C++ 错误笔记-解决swap函数与标准库的std::swap函数冲突的问题
下午写了一份代码: #include <iostream> using namespace std; // 模板1:交换基本类型的值 template<typename T> ...
- ajax发送请求时为url添加参数(使用函数)
<script> // ajax的get请求,使用函数向其url添加参数 function addURLParam(url,name,value){ url+=(url.indexOf(' ...
- myeclipse之完全破解
并不是所有的破解都是成功的,就如并不是所有的战争都会胜利一样,我们在做事情的时候,总会遇到些问题,比如Activate不成功,需要手动激活. 激活不成功就是不成功,来回的破解.卸载.重装,都还是不可能 ...
- 基于ffmpeg 直播推流和播放rtmp (IOS源码)
ios直播推流每秒能达到30帧,比安卓要强,视频采用软编码的话手机会发烫,得采用码编码,播放视频采用opengl渲染. ffmpeg初始化代码如下: int init_Code(int width, ...
- dirname(__FILE__) 的使用总结 2(转)
比如当前文件是放在(d:\www\)下,文件名是test.php. 测试的代码如下: 复制代码 代码如下: <?php echo __FILE__ ; // 取得当前文件的绝对地址,结果:D:\ ...
- busybox中的inittab解析
init进程是由内核启动的第一个(也是唯一一个)用户进程(进程ID为1),是所有进程的祖先.然后init进程根据配置文件决定启动哪些程序,init是后续所有进程的发起者. 用busybox制作的文件系 ...
- web.py使用要点
这几天有一个构建restful services的需求,我采用了web.py,之前并没有使用过,但在使用中确实给我带来了很多惊喜.当然,最大的惊喜就是简单,方便.之前开发restful服务的时候,采用 ...
- 简单解决Ubuntu修改locale的问题
本文针对的问题是“Ubuntu 安装中文语言包”“Ubuntu Server中文问题”,“Ubuntu更改语言环境”,“Ubuntu locale的设定”,“cannot change local ...