Java面向对象之static关键字
1-static关键字的使用
/*
static关键字的使用
1-static:静态的
2-static可以用来修饰:属性、方法、代码块、内部类
3-static修饰属性:静态变量(或类变量)
①属性,按是否使用static修饰,又分为:静态属性 vs 非静态属性(实例变量)。
实例属性:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。当修改其中一个对象中的非静态属性时,不会改变其他对象的属性。
静态属性:我们创建了类的多个对象。多个对象共享一个静态变量。当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的。
②static修饰符的其他说明:
1-静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用
2-静态变量的加载要早于对象的创建
3-由于类只会加载一次,则静态变量在内存中也只会存在一份:存在于方法区的静态域中
4- 类变量 实例变量
类 yes no
对象 yes yes
③静态属性举例:System.out; Math.PI;
4-static修饰方法:静态方法
①随着类的加载而加载,可以通过"类.静态方法"的方式进行调用
② 静态方法 非静态方法
类 yes no
对象 yes yes
③静态方法中,只能调用静态的方法或属性。非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性
5-static使用注意点:
在静态的方法内,不能使用this关键字、super关键字
6-开发中:
如何确定一个属性是否声明为Static的?
>属性时可以被多个对象所共享的,不会随着对象的不同而不同的。
>类中常量也通常声明为static的
如何确定一个方法是否声明为Static的?
>操作静态属性的方法,通常设置为static的
>工具类中的方法,习惯声明为static的,比如:Math,Array,Collections
*/
public class StaticTest { public static void main(String[] args) { Chinese.nation = "中国"; Chinese c1 = new Chinese(); c1.name = "李白"; c1.age = 22; Chinese c2 = new Chinese(); c2.name = "韩信"; c2.age = 21; // c1.nation = "CHN"; System.out.println(c2.nation); // 中国 Chinese.walk(); } } // 中国人 class Chinese{ String name; int age; static String nation; public void eat() { System.out.println("吃中餐"); walk(); } public static void walk() { System.out.println("人:走路"); System.out.println(nation); // 中国 // eat(); 还没在内存中加载出来所有,不能调用 } public static void speak() { System.out.println("人:讲话"); walk(); } }
2-类变量 vs 实例变量内存解析
3-static关键字的应用举例
package com.lzh.exer; /* * Static关键字的应用 */ public class CircleTest { public static void main(String[] args) { Circle c1 = new Circle(); Circle c2 = new Circle(); Circle c3 = new Circle(3.4); System.out.println("c1的id:"+c1.getId()); // 1001 System.out.println("c2的id:"+c2.getId()); // 1002 System.out.println("c3的id:"+c3.getId()); // 1003 System.out.println("创建圆的个数:"+Circle.getTotal()); // 3 } } class Circle{ private double redius; private int id; // 自动赋值 private static int total; // 记录创建元的个数 private static int init = 1001; // static声明的属性被所有对象共享 public Circle() { id = init++; total++; } public Circle(double redius) { this(); this.redius = redius; // id = init++; // total++; } public int getId() { return id; } public static int getTotal() { return total; } public double findArea() { return Math.PI * redius * redius; } }
4-static使用练习
package com.company; /* * 编写一个类实现银行账户的概念,包含的属性有“帐号”、“密 码”、“存款余额”、“利率”、“最小余额”, * 定义封装这些 属性的方法。账号要自动生成。 编写主类,使用银行账户类,输入、输出3个储户的上述信息。 * 考虑:哪些属性可以设计成static属性 * */ public class AccountTest { public static void main(String[] args) { Account account1 = new Account(); Account account2 = new Account("123456",10000); Account.setInterestRate(0.012); Account.setMinMoney(100); System.out.println(account1); System.out.println(account2); System.out.println(account1.getBalance()); System.out.println(account1.getId()); System.out.println(account1.getPassWord()); System.out.println(account1.getInterestRate()); System.out.println(account2.getBalance()); } } class Account{ private int id; private String passWord = "000000"; private double balance; private static double interestRate; // 利率共享 private static double minMoney = 1.0; // 最小余额 private static int init = 1001; // 用于自动生成id // 声明构造器 public Account() { id = init++; } public Account(String passWord,double balance) { this(); this.passWord = passWord; this.balance = balance; } public String getPassWord() { return passWord; } public void setPassWord(String passWord) { this.passWord = passWord; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } public static double getInterestRate() { return interestRate; } public static void setInterestRate(double interestRate) { Account.interestRate = interestRate; } public static double getMinMoney() { return minMoney; } public static void setMinMoney(double minMoney) { Account.minMoney = minMoney; } public int getId() { return id; } }
5-单例 (Singleton)设计模式
/*
* 单例设计模式:
* 1-采取一定的方法保证在整个的软件系统中,对 某个类只能存在一个对象实例
* 2-如何实现?
* ①饿汉式
* ②懒汉式
*
* 3-区分饿汉式和懒汉式
* 饿汉式:
* 好处->饿汉式是线程安全的
* 坏处->加载时间过长
* 懒汉式:
* 好处->延迟对象的创建
* 坏处->目前写法线程不安全 后面在修改
*/
public class SingletonTest1 { public static void main(String[] args) { // Bank bank = new Bank(); Bank bank1 = Bank.getInstace(); Bank bank2 = Bank.getInstace(); System.out.println(bank1 == bank2); // true } } // 饿汉式单例模式 class Bank{ // 1-私有化类的构造器 private Bank() { } // 2-内部创建类的对象 private static Bank instance = new Bank(); // 3-提供公共静态的方法返回类的对象 public static Bank getInstace() { return instance; } // 4-要求此对象也必须声明为静态的 }
package com.lzh.java1; /* * 单例模式懒汉式的实现 * * 懒汉式暂时还存在线 程安全问题,讲到多 线程时,可修复 * */ public class SingletonTest2 { public static void main(String[] args) { Order order1 = Order.getInstance(); Order order2 = Order.getInstance(); System.out.println(order1 == order2); // true } } class Order{ // 1-设置私有化的构造器 private Order() { } // 2-声明当前类对象,没有初始化。注意此对象必须声明为static的 private static Order instance = null; // 3-声明public static 的返回当前类对象的方法 public static Order getInstance() { if(instance == null) { instance = new Order(); } return instance; } }
/*
* 单例设计模式的优点
*/
/*
* 单例设计模式的应用举例
*/
6-类的成员之四:代码块(或初始化块)
/*
* 类的成员之四:代码块(或初始化块)
*
* 1-代码块的作用:用来初始化类、对象
* 2-代码块有修饰的话,只能使用static
* 3-分类:静态代码块 vs 非静态代码块
* 4-静态代码块
* >内部可以有输出语句
* >随着类的加载而执行,只会执行这一次
* >作用:初始化类的信息
* >可以定义多个代码块,则按照声明的先后顺序执行
* >静态代码块的执行要优于非静态代码块的执行
* >只能调用静态结构,不能调用非静态结构
*
* 5-非静态代码块
* >随着对象的创建而执行
* >内部可以有输出语句
* >每创建一个对象,就执行一次非代码块
* >作用:可以在创建对象时,对对象属性等进行初始化
* >能调用静态结构,也能能调用非静态结构
*
* 6-对属性可以赋值的位置
* ①默认初始化
* ②显示初始化
* ③构造器中初始化
* ④有了对象以后,可以通过"对象.属性"或"对象.方法"的方式,进行赋值
* ⑤在代码块中赋值
* 执行书序:① - ② / ⑤ - ③ - ④
*
* 7-判断执行顺序时:由父及子,静态先行
*/
public class BlockTest { public static void main(String[] args) { String des = Person.desc; // System.out.println(des); Person p1 = new Person(); } } class Person{ // 属性 String name; int age; static String desc = "我是一个人"; // 构造器 public Person() { } public Person(String name,int age) { this.name = name; this.age = age; } // 静态代码块 static { System.out.println("Hello statci block"); desc = "我是一个爱学习的人"; info(); // eat(); // 不可调用非静态结构 } // 非静态代码块 { System.out.println("Hello block"); info(); this.name = "alex"; } // 方法 public void eat() { System.out.println("吃饭"); } @Override public String toString() { // TODO Auto-generated method stub // return super.toString(); return "Person[name="+name+", age="+age+"]"; } public static void info() { System.out.println("我是一个快乐的人"); } }
7-final关键字
/*
* final:最终的
* 1-final可以用来修饰的结构:类、方法、变量
*
* 2-final 用来用来修饰一个类:此类不能再被子类继承
* 比如:String类、System类、StringBuffer类
*
* 3-final 用来修饰方法:表明此方法不可以被重写
* 比如:Object类中的getClass方法
*
* 4-final 修饰变量:此时的"变量"称为是一个常量
* ①final修饰属性:可以考虑赋值的位置有:显示初始化、代码块中初始化、构造器
* ②final修饰局部变量:
* 修饰形参时,表明此形参是一个常量,只能在方法体内调用传入的实参,不能修改
*
* 5-static final 用来修饰:全局常量
*/
public class finalTest { public static void main(String[] args) { } final int height = 10; final int COLOR = 1; // 显示初始化 final int WIDTH; final String name; public void setHeight(int height) { this.height = height; // 报错 } { WIDTH = 3; // 代码块中初始化 } public finalTest() { name = "alex"; // 构造器中初始化 } public void showNumber(final int number) { number = 10; // 报错 // final修饰形参变量后,只能在方法体内调用传入的实参,不能修改 System.out.println(number); } } final class Person{ // final修饰类后,不能再被子类继承 } class Man extends Person{ // 报错 } class Animal{ public final void show() { } } class Dog extends Animal{ // public void show() { // 报错,不能再被重写 // } }