静态关键字:static
static的作用、修饰成员变量的用法
static是静态的意思,可以修饰成员变量,表示该成员变量只在内存中只存储一份,可以被共享访问、修改。
静态变量分为2类:
- 静态成员变量(有static修饰,属于类,内存中加载一次):表示如在线人数信息、等需要被共享的信息,可以被共享访问。
- 实例成员变量(无static修饰,存在每个对象中):常表示姓名name、年龄age、等属于每个对象的信息。
static修饰成员变量的内存原理
static修饰成员方法的基本用法
成员方法分类:
静态成员方法(有static修饰,属于类),建议用类名访问,也可以用对象访问。
实例成员方法(无static修饰,属于对象),只能用对象触发访问。
static修饰成员方法的内存原理
static实际应用案例:使用静态方法定义工具类
public class VerifyTool {
/**
私有化构造器
原因:工具类不需要对外创建对象,直接用类名访问即可
*/
private VerifyTool() {
}
/**
静态方法
*/
public static String createCode(int n) {
// 1. 用String开发验证码
String chars = "qwertyuiopasdfghjklzxcvbnmZXCVBNMASDFGHJKLQWERTYUIOP0123456789";
// 2. 定义一个变量用于存储5位随机字符
String code = "";
// 3. 循环
Random r = new Random();
for (int i = 0; i < n; i++) {
int index = r.nextInt(chars.length());
// 4. 对应索引提取字符
code += chars.charAt(index);
}
return code;
}
}
public class ToolClass {
public static void main(String[] args) {
// 验证码
System.out.println("验证码: " + VerifyTool.createCode(5));
}
}
public class ArraysUtils {
/**
构造器私有化
*/
private ArraysUtils() {
}
/**
定义静态方法:工具方法
*/
public static String toString(int[] arr) {
if (arr == null){
return null;
}else {
String result = "[";
for (int i = 0; i < arr.length; i++) {
result += (i == arr.length - 1 ? arr[i] : arr[i] + ",");
}
result += "]";
return result;
}
}
/**
定义静态方法:工具方法
*/
public static double getAerage(int[] arr) {
int sum = 0;
int max = arr[0],min = arr[0];
for (int i = 0; i < arr.length; i++) {
// 获取最大值
if (arr[i] > max){
max = arr[i];
}
// 获取最小值
if (arr[i] < min) {
min = arr[i];
}
//总和
sum += arr[i];
}
return (sum - max - min)*1.0 / (arr.length -2);
}
}
public class Demo {
public static void main(String[] args) {
int[] arr = {10, 20, 50, 34, 100};
System.out.println("数组内容为:" + ArraysUtils.toString(arr));
System.out.println("去掉最大、最小值后的平均值为:" + ArraysUtils.getAerage(arr));
}
}
static的注意事项
public class Demo {
// 静态成员变量
public static int num;
// 实例成员变量
private String name;
//静态成员方法
public static void inAddr() {
System.out.println("666");
}
public void sing() {
}
// 实例方法可以直接访问静态成员和实例成员
public void run() {
System.out.println(num);
System.out.println(Demo.num);
System.out.println(name);
sing();
Demo.getMax();
getMax();
}
public static void getMax() {
// 1. 静态方法可以直接访问静态成员变量
System.out.println(Demo.num);
System.out.println(num);
// 2. 静态方法可以直接访问静态成员方法
inAddr();
}
}
static应用知识:代码块
代码块的分类、作用
public class TestDemo1 {
public static String schoolName;
public static void main(String[] args) {
//静态代码块的特点,基本作用
System.out.println("=======main方法被执行========");
System.out.println(schoolName);
}
//静态代码块特点:与类一起加载,自动触发一次,优先执行
//静态代码块作用:可以在程序加载时进行静态数据初始化
static {
System.out.println("==静态代码块被触发执行==");
schoolName = "清华大学";
}
}
public class TestDemo1 {
private String name;
/**
属于对象的,与对象一起加载,自动触发执行
作用:
*/
{
System.out.println("==实例(构造)代码块被触发执行==");
name = "张三";
}
public TestDemo1() {
System.out.println("构造器被触发执行");
}
public static void main(String[] args) {
//构造(实例)代码块的特点,基本作用
System.out.println("=======main方法被执行========");
TestDemo1 t1 = new TestDemo1();
System.out.println(t1.name);
TestDemo1 t2 = new TestDemo1();
System.out.println(t2.name);
}
}
静态代码块的应用案例
public class TestDemo1 {
/**
模拟初始化操作
花色:♠,♣,♥,♦
1. 准备一个容器,存储54张牌对象,这个容器建议使用静态集合,静态静态只加载一次
*/
public static ArrayList<String> cards = new ArrayList<String>();
/**
2. 在游戏启动前需要加载54张牌放进去,使用静态代码块进行初始化
*/
static {
// 3. 加载54张牌
// 4. 准备4种花色,类型确定,个数确定
String[] colors = {"♠", "♣", "♥", "♦"};
// 5. 定义点数
String[] size = {"3", "4", "5", "6", "7", "8", "9",
"10", "J", "Q", "K", "A", "2"};
// 6. 先遍历点数再组合花色
for (int i = 0; i < size.length; i++) {
//size[i]
for (int j = 0; j < colors.length; j++) {
cards.add(size[i] + colors[j]);
}
}
//添加大小王
cards.add("大王");
cards.add("小王");
}
public static void main(String[] args) {
System.out.println("新牌" + cards);
}
}
static应用知识:单例设计模式
设计模式、单例设计模式介绍、饿汉单例模式
/**
饿汉单例方式定义单例类
*/
public class SingleInstance {
// 2. 定义一个公开的、静态的成员变量
// 饿汉:在这里加载静态变量的时候就会加载对象了
public static SingleInstance instance = new SingleInstance();
// 与public static int instance = 100意思一样;
// 1. 将构造器藏起来
private SingleInstance() {
}
}
public class Test {
public static void main(String[] args) {
SingleInstance singleInstance1 = SingleInstance.instance;
SingleInstance singleInstance2 = SingleInstance.instance;
SingleInstance singleInstance3 = SingleInstance.instance;
System.out.println(singleInstance1);
System.out.println(singleInstance2);
System.out.println(singleInstance3);
System.out.println(singleInstance1 == singleInstance3);
/**
结果:
com.day6.SingleInstance@4eec7777
com.day6.SingleInstance@4eec7777
com.day6.SingleInstance@4eec7777
true
*/
}
懒汉单例模式
/**
懒汉单例方式定义单例类
*/
public class SingleInstance {
// 2. 创建一个静态的成员变量,存储本类的对象
//注意:此时不能初始化对象
private static SingleInstance instance; //null
// 1. 私有化构造器
private SingleInstance(){
}
// 3. 定义一个方法让其他地方可以来调用获取对象
public static SingleInstance getInstance(){
if (instance == null) {
// 第一次来获取对象
instance = new SingleInstance();
}
return instance;
}
}
public class Test {
public static void main(String[] args) {
SingleInstance s1 = SingleInstance.getInstance();
SingleInstance s2 = SingleInstance.getInstance();
SingleInstance s3 = SingleInstance.getInstance();
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(s1 == s3);
/**
结果:
com.day6.SingleInstance@4eec7777
com.day6.SingleInstance@4eec7777
com.day6.SingleInstance@4eec7777
true
*/
}
}
面向对象三大特征之二:继承
继承概述
public class People {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Student extends People{
/**
独有的行为
*/
public void study() {
System.out.println("学生" + getName() +"正在学习");
}
}
public class Teacher extends People{
/**
独有的行为
*/
public void teach() {
System.out.println(getName() + "老师正在上课");
}
}
public class Test {
public static void main(String[] args) {
//创建子类对象,看是否可以使用父类的属性和行为
Student student = new Student();
student.setName("小明"); // 父类的
System.out.println(student.getName()); // 父类的
student.study(); //子类的
Teacher teacher = new Teacher();
teacher.setName("小王");
System.out.println(teacher.getName()); // 父类的
teacher.teach(); //子类的
/**
结果:
小明
学生小明正在学习
小王
小王老师正在上课
*/
}
}
继承的设计规范、内存运行原理
/**
角色类 父类
*/
public class Role {
private String name;
private int age;
//查看课表
public void queryCourse() {
System.out.println(name + "正在查看课程信息");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
/**
学生类 子类
*/
public class Student extends Role {
private String className;
public void writeInfo() {
System.out.println(getName() + "说:学习状态不错");
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
}
/**
老师类 子类
*/
public class Teacher extends Role {
private String partName;
public void question() {
System.out.println(getName() + "老师已经发布了问题");
}
public String getPartName() {
return partName;
}
public void setPartName(String partName) {
this.partName = partName;
}
}
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.setName("小明");
Teacher teacher = new Teacher();
teacher.setName("老王");
student.writeInfo();
teacher.question();
/**
结果:
小明说:学习状态不错
老王老师已经发布了问题
*/
}
}
继承的特点
继承后:成员变量、成员方法的访问特点
class Animal {
public String name = "动物父类";
}
class Wolf extends Animal {
public String name = "动物子类";
public void showName() {
String name = "局部名称";
System.out.println(name); // 局部name
System.out.println(this.name); // 子类name
System.out.println(super.name); // 父类name
}
}
/**
* 结果:
局部名称
动物子类
动物父类
*/
class People {
public void run() {
System.out.println("跑");
}
}
class Student extends People {
public void run() {
System.out.println("牛逼");
}
public void go() {
run(); // 子类的
super.run(); //父类的
}
}
/**
* 结果:
牛逼
跑
*/
继承后:方法重写
public class Phone {
public void call() {
System.out.println("开始打电话");
}
public void sendMessage() {
System.out.println("开始发信息");
}
}
public class NewPhone extends Phone{
/**
* 方法重写
*/
@Override
public void call() {
super.call();
System.out.println("支持视频通话");
}
@Override
public void sendMessage() {
super.sendMessage();
System.out.println("支持发送图片和视频");
}
}
public class Test {
public static void main(String[] args) {
NewPhone newPhone = new NewPhone();
newPhone.call();
newPhone.sendMessage();
/**
* 结果:
开始打电话
支持视频通话
开始发信息
支持发送图片和视频
*/
}
}
继承后:子类构造器的特点
继承后:子类构造器访问父类有参构造器
this、super使用总结
public class Student {
private String name;
private String schoolName;
public Student() {
}
public Student(String name) {
this(name,"大学");
}
public Student(String name, String schoolName) {
this.name = name;
this.schoolName = schoolName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSchoolName() {
return schoolName;
}
public void setSchoolName(String schoolName) {
this.schoolName = schoolName;
}
}
public class Test {
public static void main(String[] args) {
Student s1 = new Student("老王","清华大学");
System.out.println(s1.getName());
System.out.println(s1.getSchoolName());
Student s2 = new Student("老潘");
System.out.println(s2.getName());
System.out.println(s2.getSchoolName());
/**
* 结果:
老王
清华大学
老潘
大学
*/
}
}