static 关键字
被static关键字修饰的函数一般被称为静态函数 没有被static关键字修饰的函数 一般称为非静态函数。同理 被static关键字修饰的成员变量 叫静态的成员变量 ,没有被static修饰的叫非静态成员变量。
成员变量+static=静态变量
静态变量:当我们在设计类的时候 发现多个对象中有共享数据的时候 我们就可以把这个共享的数据 定义为静态变量 对于 String name; String age; static String country="China";来说 name、age虽然每个对象都有 但是值不一定一样 对象的特有数据->成员变量;country虽然每个对象也都有 但是值一样 对象的共有数据-> 静态变量。
静态的东西从堆中对象的空间里抽取出来了 放到静态方法区。
举个例子来说:
大家伙来公司上课 你要喝水 对于水杯/水壶来说是特有的,对于饮水机来说是共有。
上述可以知道 共有的数据存在于一个特定的空间 静态方法区。
去学校上课 饮水机在 你下课回家 饮水机还在
上述又说明一个问题 共有的数据 要 活的比 对象 长。
成员函数+static=静态函数
静态函数意味着就是对象的共有行为吗?不是的
静态函数 :只能访问静态的成员变量 如果访问非静态成员变量 那么无法通过编译,无需创建对象,使用类名就可以直接调用。
非静态函数:既能访问静态的成员变量,也能访问非静态的成员变量 只能通过创建对象的方式进行调用。
注意: 静态变量有默认初始化值,也有显示初始化;静态的成员变量和静态的函数无需创建对象通过类名进行访问。静态函数和静态成员变量 被整个程序共用 相当于共享。被static修饰的内容 在代码程序中会按照顺序进行加载, 如果主函数在下面,那么会优先加载静态成员变量和成员函数。
对于类的分类:
实体类:
就是为了描述一个事物 Person Point; 类中内容基本上都是成员函数/成员变量, 也会存在一个静态成员
工具类:
提供一些已经被实现好的功能 向外部供应,所以工具类中基本上全都是静态函数例如: 类.Xxx 类.Xxx() Math Arrays
为啥工具类中都是静态?
(1)共有的
(2)长时间存在
(3)加载一次 后期随便使用
一个道理:当我们钉一个钉子的时候 找榔头,你是造一个榔头 还是用已存在的榔头? 如果工具类可以被创建对象 是不是就想用的时候去创建,就会造成效率较低
主类/测试类:
主要用于运行/测试代码;这个类中会有主函数的存在;实体类是可以存在主函数的 但是不推荐;工具类一般不会存在主函数
建议 :一个类一个文.java件
拓展:
通过 对象.变量去调用时 ,我们查找时:
1.先去堆内存中对象的所属空间里找
2.再去静态方法区中该对象所属类的空间里找通过 对象.函数去调用时 ,我们查找时:
1.先去非静态方法区中该对象所属类的空间里找
2.再去静态方法区中该对象所属类的空间里找对于成员函数内部在调用变量时的顺序:
1.先找局部变量
2.去堆中对象空间中找
3.去静态区该对象所属类的空间里找
static 关键字示例:
class StaticDemo{
public static void main(String[] args){
Chinese c1=new Chinese();
Chinese c2=new Chinese();
Chinese c3=new Chinese();
//通过 对象.变量
//1.先去堆内存中对象的所属空间里找
System.out.println(c1.name); //成员变量
//2.再去静态方法区中该对象所属类的空间里找
System.out.println(c1.country); //静态变量
//通过 对象.函数
//1.先去非静态方法区中该对象所属类的空间里找
c1.show();
//2.再去静态方法区中该对象所属类的空间里找
c1.haha();
System.out.println(Chinese.country);
Chinese.haha();
//Chinese.show();
System.out.println(Chinese.momo);
System.out.println(Chinese.kaka);
}
}
class Chinese{
static int momo;
static boolean kaka;
String name; //姓名
String age; //年龄
static String country="China"; //国籍
//无法从静态上下文中引用非静态
public void show(){
String name="旺财";
/*
成员函数内部在调用变量时的顺序:
1.先找局部变量
2.去堆中对象空间中找
3.去静态区该对象所属类的空间里找
比如说:
我要喝水 水从哪里来
1.如果你的嘴里已经有水 直接喝
2.如果你的嘴里没水 杯子里有水 拿杯子喝
3.如果你的嘴里没水 杯子没水 去饮水机
(先不考虑继承的情况下)
*/
System.out.println(name+age+country);
}
public static void haha(){
System.out.println("哈哈");
}
public static void main(String[] args){
}
}
对象的内存图解III
1.javac 将Java源代码进行编译 生成字节码文件
2.java 将字节码文件加载进虚拟机中 开始运行程序 。字节码具体被加载在方法区里面;方法区可以大致分为 非静态方法区/静态方法区;所有非静态的代码(二进制)内容加载进非静态去;所有静态的代码(二进制)内容加载进静态区;JVM接下来会根据参数(java 字节码文件名(类名)) 去静态区找主函数, 将主函数代码加载进虚拟机栈 开始运行/
静态变量与成员变量的区别
1.生命周期
成员变量随着对象的创建而创建 随着对象的消亡而消亡
静态变量随着类的加载而创建 随着程序结束而消失
2.调用方式
成员变量必须先创建对象 在通过对象去调用
静态变量可以被对象调用 也可以直接用类调用
3.存储位置
成员变量存在于堆内存中对象的所属空间里
静态变量存在于静态方法区中类的所属空间里
4.命名
成员变量-对象的特有属性
静态变量-对象的共有属性 类成员
代码块
代码块 { ... }
局部代码块:存在于函数当中(包括函数) for(){...} if(){...}
构造代码块:直接在类中出现的{...}
当对象创建一次 构造代码块执行一次
作用等同于构造函数
静态代码块:直接在类中出现的static{...}
当类被加载的时候 仅且只执行一次
作用于 对类进行一些初始化操作 JDBC
示例:
class CodeBlock{
{
System.out.println("构造代码块");
}
static{
System.out.println("静态代码块");
}
public static void main(String[] args){
CodeBlock c1=new CodeBlock();
CodeBlock c2=new CodeBlock();
CodeBlock c3=new CodeBlock();
}
}
单例模式
设计模式:
设计模式:就是我们的前辈们总结出来的一些编码技巧
它并不是随着Java的诞生而诞生的;它是由Java的广大使用者总结出来的一套编码经验,常见26种。
单例模式:
单例模式:使用场景是 某一个类只能创建一个对象
比如某一个朝代的皇帝 只能是唯一的
1.既然只能创建一个对象的话 就得不能让外界去创建对象
限制使用new不现实; 只能从对象的创建流程中考虑 只要有一个步骤不行 对象就创建不出来;开辟空间分配地址 是由计算机底层决定 我们也控制不了; 构造函数执行 只需要将构造函数私有化即可
2.既然外界不能创建对象 我们还得保证对象的创建
因此我们只能在类内部创建对象。Single s=new Single();。由于不能写成 成员变量的形式 所以要加上private static语句。
3.内部创建出对象 还得向外界提供
因为private 外界不能直接访问,所以见解 向外界提供一个函数 外界通过调用函数获取对象.
示例:
//饿汉式 比较急 所以直接返回对象
/*
class Single{
private static Single s=new Single();
private Single(){}
public static Single getInstance(){
return s;
}
}
*/
//饱汗式 比交满 不急 判断一下
class Single{
private static Single s;
private Single(){}
public static Single getInstance(){
if(s==null){
s=new Single();
}
return s;
}
}
//测试类
class SingleTest{
public static void main(String[] args){
Single s1=Single.getInstance();//调用
Single s2=Single.getInstance();
Single s3=Single.getInstance();
System.out.println(s1==s2);//对比
System.out.println(s2==s3);
}
}