目录
Static
作用:static是静态的意思,可以修饰成员变量,表示该成员方法只存在内存中只存储一份,可以被共享访问、修改。
public class User{
//成员变量
public static int Number=100;
private String name;
private int age;
...
}
成员变量
静态成员变量
public class User{
//静态成员变量
public static String Number=100;
}
类名.静态成员变量(推荐)
对象.静态成员方法(不推荐)
实例成员变量
无static修饰,存在于每个对象中。常表示姓名、年龄age、等属于每个对象的信息。
public class User{
public static String Number =100;
//实例成员变量
private String name;
private int age;
...
}
对象.实例成员变量
案例1
编写一个在线人数信息,进来一次,加一个人。
首先,创建一个类User,定义一个静态成员变量(有static),给一个初始值200。其次,再定义实例成员变量(无static)。创建名字、年龄。
public class User {
//在线人数信息
public static int Number=200;
//实例成员变量 不加static
private String name;
private Integer age;
}
调用
1.静态成员变量 类名.静态成员变量
User.Number++;
同一个类中访问静态成员变量,类名可以省略。
System.out.println(Number);
2.实例成员变量 对象.实例成员变量
注意:直接访问成员变量,会报错。为什么?因为name是属于对象的,现在name还没有加载,现在访问name,必要访问哪个对象里的name呢?虽然放在类里面,但是不一定能访问。在类里面,是属于每一个对象的。
System.out.println(name); 报错 访问不了
如果一定要访问实例成员变量,就需要创建对象。
User user=new User();
user.name="菠萝";
user.age=10;
System.out.println(user.age);
System.out.println(user.name);
静态成员变量也可以用对象访问。why? 因为静态成员变量只有一个,是对所有共享的。 对象.静态成员变量
user.Number++;
BUT!!!Java不推荐这样用,写的时候没有提示,写到后面才有提示,说明不希望你这样用。用类名访问会更加方便,没必要拿对象访问。
再创建一个对象user1访问静态成员变量
User user1=new User();
user1.name="吹雪";
user1.age=13;
System.out.println(user1.age);
System.out.println(user1.name);
user1.Number++;
System.out.println(Number);
输出:Number 加1,又加1,变成202。
内存解析
static内存解析:
1、静态的变量或者静态方法存在于方法区的。静态的结构不会被垃圾回收。
2、不属于某一个实例对象,只存在于方法区。调用静态结构,直接用类名.属性名(方法名)
的方式。
static修饰成员方法的基本用法
静态成员方法(有static修饰,属于类),建议用类名访问,也可以用对象访问。
实例成员变量(无static修饰,属于对象),只能用对象出发访问。
使用场景:
1.表示对象自己的行为的,且方法中需要访问实例成员的,则该方法必须申明成实例方法。
2.如果该方法是以执行一个通用功能为目的,或者需要方便访问,则可以申明成静态方法。
新建一个学生类,定义姓名、年龄
package d1_static_field;
public class Student {
private String name;
private Integer age;
}
定义一个实例方法(无static,属于对象的,通常表示对象自己的行为,可以访问对象的成员变量)
public void study() {//实例方法
System.out.println(name + "在学习");
//可以访问name,因为study属于属于对象,name也属于对象,他们在同一个对象中,所以可以访问
}
定义一个静态成员方法(有static,属于类,可以被类和对象共享访问)
public static void getMax(Integer a, Integer b) {
System.out.println(a > b ? a : b);
}
测试
public static void main(String[] args) {
//访问静态成员方法 类名.静态方法
Student.getMax(3,4);
//同一个类中访问静态成员方法,可以省略类名不写
getMax(1,0);
//2.访问实例成员方法 对象名.实例方法
Student student=new Student();
student.name="菠萝";
student.age=23;
student.study();
//3.对象.静态方法(不推荐)
student.getMax(2,9);
}
1.成员方法的分类和访问分别是什么样的?
静态成员方法(有static修饰,属于类和对象共享)访问格式类名.静态成员方法。
对象.静态成员方法。(不推荐)
实例成员方法(无static修饰,属于对象)的访问格式:对象.实例成员方法。
2.每种成员方法的使用场景是怎么样的?表示对象自己的行为的,且方法中需要访问实例成员的,则该方法必须申明成实例方法。
如果该方法是以执行一个通用功能为目的,或者需要方便访问,则可以申明成静态方法。
static访问注意事项(面试常考!!)
1.静态方法只能访问静态的成员变量(或者静态方法),不可以直接访问实例成员。
因为实例成员是属于对象的,不可以直接访问,可以创建对象去访问(间接访问)2.实例方法可以访问静态的成员,也可以访问实例成员。
因为静态成员和静态方法都是共享的,所以实例方法在任何地方都可以直接访问
3.静态方法中不可以出现this关键字的
this关键字代表当前对象,静态方法不是用对象调的,是用类调的,静态方法没有对象
工具类
对于一些应用程序中多次需要用到的功能,可以将这些功能封装成静态方法(静态方法方便调用),放在一个类中,这个类就是工具类。
工具类的作用:一是方便调用,二是提高了代码复用。
案例
用String开发验证码。首先定义一个字符串,其次,定义一个变量 用于存储5个随机的字符作为验证码,然后循环,再根据对应索引提取字符。
package d1_static_field;
import java.util.Random;
public class StaticTools {
public static void main(String[] args) {
//用String开发验证码
String chars="qwertyuiopasdfghjklzxcvbnm";
//2.定义一个变量 用于存储5个随机的字符作为验证码
String code="";
//3.循环
Random random=new Random();
for (int i = 0; i < 5; i++) {
int index=random.nextInt(chars.length());
//4.对应索引提取字符
code+=chars.charAt(index);
}
System.out.println("验证码:"+Verification.createCode());
}
}
注意:如果多个地方都需要验证码,还要继续写相同的代码,带来大量代码的重复。这时候就可以定义一个工具类来解决这个问题。
再定义一个类,定义一个功能把验证码的功能(静态方法)进行封装
package d1_static_field;
import java.util.Random;
public class Verification {
/*静态方法*/
public static String createCode(int n){//定义一个参数n来接,传几返几
//用String开发验证码
String chars="qwertyuiopasdfghjklzxcvbnm";
//2.定义一个变量 用于存储5个随机的字符作为验证码
String code="";
//3.循环
Random random=new Random();
for (int i = 0; i < n; i++) {//有些要验证码需要好多位,因此把5改成n👆
int index=random.nextInt(chars.length());
//4.对应索引提取字符
code+=chars.charAt(index);
}
return code;//把验证码返回,不是输出,谁调我,我就返给谁
}
}
package d1_static_field;
public class StaticTools {
public static void main(String[] args) {
System.out.println("验证码:"+Verification.createCode(5));
}
}
工具类原理和延伸
一次编写,处处可用
建议将工具类的构造器私有,不让工具类对外产生对象。
为什么?
因为工具类不需要对外创建对象,它的调用是直接用类名访问静态方法,里面全是静态方法,创建对象干嘛?除了浪费内存还能干嘛呢?所以要把工具类的构造器私有,让所有类名来访问就可以了。它不是为了作对象,它是来调方法的。
思考:为什么工具类中的方法不用实例方法来做?
实例方法需要创建对象调用,此时用对象只是为了调用方法,这样只会浪费内存。
1.工具类是什么,有什么好处?
内部都是一些静态方法,每个方法完成一个功能一次编写,处处可用,提高代码的重用性。
2.工具类有什么要求?
建议工具类的构造器私有化处理。
代码块
代码块是类的5大成分之一(成员变量、构造器,方法,代码块,内部类),定义在类中方法外。
在Java类下,使用{ }括起来的代码被称为代码块。
代码块分为:静态代码块、构造代码块(实例代码块)
静态代码块
格式:static{ }
特点:需要通过static关键字修饰,随着类的加载而加载(与类一起执行),并且自动触发、只执行一次
使用场景∶在类加载的时候做一些静态数据初始化的操作,以便后续使用。
static {
System.out.println("静态代码块被触发执行");
System.out.println(Name);
}
实例代码块(构造代码块)
随着对象一起走的,优先于构造器先执行的
格式:{ }
特点:每次创建对象,调用构造器执行时,都会执行该代码块中的代码,并且在构造器执行前执行(每次创建实例,都会被调用一次,用的很少)
使用场景:初始化实例资源
{
// 实例代码块
System.out.println("实例代码块...");
}
匿名对象
Test test =new Test();
//省略名字变成:
new Test();
设计模式:单例设计模式 饿汉单例模式
设计模式:设计模式是一套被前人反复使用、多数人知晓、经过分类编目的代码设计经验的总结,后来者可以直接拿来解决问题。
单例模式
可以保证系统中,应用该模式的这个类永远只有一个实例,即一个类永远只能创建一个对象。
实现方式:饿汉单例模式 懒汉单例模式
饿汉单例模式
在用类获取对象的时候,对象已经提前为你创建好了。
设计步骤:
1.定义一个类,把构造器私有
把构造器私有是为了只能在当前类里访问。
2.定义一个静态变量存储一个对象
静态变量只能加载一次,所以右边的也只能new一次,这样就可以产生单例。
案例:
定义一个公开的静态的成员变量存储一个类的对象
public static Single instance=new Single();
饿汉:在这里加载静态变量的时候就会创建对象
测试
public static void main(String[] args) {
Single single=Single.instance;
Single single1=Single.instance;
Single single2=Single.instance;
System.out.println(single);
System.out.println(single1);
System.out.println(single2);
}
结果是一样的
懒汉单例模式
在真正需要该对象的时候,才去创建一个对象(延迟加载对象)。
设计步骤:
1.定义一个类,把构造器私有
2.定义一个静态变量存储一个对象
3.提供一个返回单例对象的方法
package d1_static_field;
/*懒汉单例模式*/
public class Single1 {
public static Single1 instance;
public Single1() {
}
public static Single1 getInstance() {
if (instance==null){
//第一次来获取对象
instance=new Single1();//new一个对象,原封不动的交给变量
}
return instance;
}
}
总结
今天学了static,修饰成员变量、方法、内存原理、工具类、代码块、包括静态代码块、实例代码块、单例设计模式,包括饿汉单例模式和懒汉单例模式等等,内容有点多,设计模式和代码块那部分掌握的不是很好,后续还需要看视频巩固。