单例模式及static关键词的使用
1:static关键字
static关键字的使用
*
* 1. static:静态的
* 2. 可以用来修饰:属性、方法、内部类、代码块
*
* 3. 使用static修饰属性:
*
* 3.1 回顾变量按照在类中声明的位置来分:
* 成员变量(属性):
* 类变量(或静态变量)
* 实例变量(或非静态变量)
* 局部变量:
* 方法内、构造器内、代码块内定义的
* 方法形参、构造器形参
* 3.2 非静态属性的特点:
* 每当我们创建一个类的实例,内存中就会在堆空间里分配一套类的非静态变量。类的多个实例的相同属性之间没有任何关系。
* 3.3 静态属性的特点:
* ① 类的多个实例共享类的静态属性
* ② 类的静态属性在内存中就只有一份。存在于方法区的静态域中。
* ③ 类的静态属性随着类的加载而加载。
* (对比:类的非静态属性随着对象的创建而加载)
* ④ 静态属性 非静态属性
* 类 yes no
* 对象 yes yes
* ⑤ 当通过一个对象修改静态属性时,会影响到其它对象对此静态属性的调用。
*
* 4. 使用static修饰方法:
* ① 随着类的加载而加载
* ② 静态方法 非静态方法
* 类 yes no
* 对象 yes yes
* ③ 静态方法内只能调用静态的属性、静态的方法。不能调用非静态的结构:属性、方法
* 非静态的方法内可以调用静态的结构或非静态的结构:属性、方法
*
*
* 5. 什么情况下适合将属性声明为static的?
* ① 当一个类的多个对象关于某一属性的值都是相同时,可以声明为static的。即:没有必要
* 给每个对象分配一份此属性的值时。
* ② 工具类中的属性通常都是静态的。
*
* 什么情况下适合将方法声明为static的?
* ① 通常操作静态属性的方法设置为静态的。(比如:get和set方法)
* ② 工具类中的方法通常都是静态方法
*
public class StaticTest {
public static void main ( String[ ] args) {
Chinese c1 = new Chinese ( ) ;
c1. name = "陈明" ;
c1. age = 39 ;
c1. nation = "CN" ;
Chinese c2 = new Chinese ( ) ;
c2. name = "张璐翔" ;
c2. age = 35 ;
c2. nation = "中国" ;
c1. info ( ) ;
c2. info ( ) ;
System. out. println ( Chinese. nation) ;
Chinese. show ( ) ;
}
}
class Chinese {
String name;
int age;
static String nation;
public void info ( ) {
System. out. println ( "name = " + name + ", age = " + age + ", nation = " + nation) ;
show ( ) ;
}
public static void show ( ) {
System. out. println ( "我是中国人!!" ) ;
System. out. println ( "nation = " + nation) ;
}
}
public class CircleTest {
public static void main ( String[ ] args) {
Circle c1 = new Circle ( 1.2 ) ;
System. out. println ( c1) ;
Circle c2 = new Circle ( 2.2 ) ;
System. out. println ( c2) ;
Circle c3 = new Circle ( ) ;
System. out. println ( c3) ;
System. out. println ( "创建的圆的个数为:" + Circle. getCircleInstanceCount ( ) ) ;
}
}
class Circle {
private double radius;
private int id;
private static int init = 1001 ;
private static int circleInstanceCount;
public Circle ( double radius) {
this . radius = radius;
this . id = init++ ;
circleInstanceCount++ ;
}
public Circle ( ) {
this . id = init++ ;
circleInstanceCount++ ;
}
@Override
public String toString ( ) {
return "Circle{" +
"radius=" + radius +
", id=" + id +
'}' ;
}
public int getId ( ) {
return id;
}
public static int getCircleInstanceCount ( ) {
return circleInstanceCount;
}
public double getRadius ( ) {
return radius;
}
public void setRadius ( double radius) {
this . radius = radius;
}
}
public class AccountTest {
public static void main ( String[ ] args) {
Account acct1 = new Account ( ) ;
Account acct2 = new Account ( "qwerty" , 3000 ) ;
Account acct3 = new Account ( "asdfg" , 2000 ) ;
System. out. println ( acct1) ;
System. out. println ( acct2) ;
System. out. println ( acct3) ;
}
}
class Account {
private int id ;
private String password = "000000" ;
private double balance;
private static double interestRate;
private static double minBalance;
private static int init = 1000 ;
public Account ( ) {
this . 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 static double getInterestRate ( ) {
return interestRate;
}
public static void setInterestRate ( double interestRate) {
Account. interestRate = interestRate;
}
public static double getMinBalance ( ) {
return minBalance;
}
public static void setMinBalance ( double minBalance) {
Account. minBalance = minBalance;
}
public int getId ( ) {
return id;
}
public double getBalance ( ) {
return balance;
}
@Override
public String toString ( ) {
return "Account{" +
"id=" + id +
", password='" + password + '\'' +
", balance=" + balance +
'}' ;
}
}
2:单例模式
* 1.设计模式:是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模免去我们自己再思考和摸索。
* 就像是经典的棋谱,不同的棋局,我们用不同的棋谱。
*
* 经典的设计模式有23种
创建型模式,共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共7种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
对软件设计模式的研究造就了一本可能是面向对象设计方面最有影响的书籍:《设计模式》:《Design Patterns: Elements of Reusable Object-Oriented Software》(即后述《设计模式》一书),由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 合著(Addison-Wesley,1995)。这几位作者常被称为"四人组(Gang of Four)",而这本书也就被称为"四人组(或 GoF)"书。
2. 单例模式(单子模式,singleton):在整个的软件系统中,对某个类只能存在一个对象实例
*
* 3. 如何实现单例模式:
* 饿汉式、懒汉式
*
* 对比?
* 懒汉式好:延迟了对象的创建
* 但有线程安全问题。
* 饿汉式好:没有线程的安全问题。
public class SingletonTest {
public static void main ( String[ ] args) {
Bank bank1 = Bank. getInstance ( ) ;
Bank bank2 = Bank. getInstance ( ) ;
System. out. println ( bank1 == bank2) ;
}
}
class Bank {
private Bank ( ) {
}
private static Bank bank = new Bank ( ) ;
public static Bank getInstance ( ) {
return bank;
}
}
public class SingletonTest1 {
public static void main ( String[ ] args) {
Application app1 = Application. getInstance ( ) ;
Application app2 = Application. getInstance ( ) ;
System. out. println ( app1 == app2) ;
}
}
class Application {
private Application ( ) { }
private static Application app = null;
public static Application getInstance ( ) {
if ( app == null) {
app = new Application ( ) ;
}
return app;
}
}
3:体会main()
/**
* main()的理解
* 1. 作为程序的入口
* 2. 可以看做是一个普通的静态方法
* 3. 除了使用Scanner之外,也可以使用main()从控制台传入需要的数据。都作为String
* 类型的变量接收。
* @author Begonia_sea
* @create 2020-07-08
*/
public class MainDemo {
public static void main(String args[]) {
Main.main(new String[10]);
}
}
class Main{
public static void main(String[] args) {
for(int i = 0;i < args.length;i++){
args[i] = "args_" + i;
System.out.println(args[i]);
}
}
}
如何在调用main()时,传参数
4:代码块
* 类的成员之四:代码块的使用
*
* 1. 从格式上讲,命名为:代码块
* 从功能上讲,命名为:初始化块
*
* 2.代码块的分类:静态代码块 、 非静态代码块
*
* 3. 静态代码块:
* 1. 内部可以编写执行语句
* 2. 随着类的加载而执行
* 3. 静态代码块的执行要早于非静态代码块
* 4. 静态代码块只执行一次
* 5. 如果类中定义了多个静态代码块,则按照声明的先后顺序执行
* 6. 在内部可以调用当前类中的静态结构:属性、方法。不能调用非静态的结构
* 7. 作用:用来初始化当前类的静态属性。
*
*
* 4. 非静态代码块:
* 1. 内部可以编写执行语句
* 2. 随着对象的创建而执行
* 3. 每创建一个对象,非静态代码块就执行一次
* 4. 如果类中定义了多个非静态代码块,则按照声明的先后顺序执行
* 5. 在内部可以调用当前类中的静态结构和非静态结构:属性、方法
* 6. 作用:用来初始化创建的对象的实例变量。
public class BlockTest {
public static void main ( String[ ] args) {
Person p1 = new Person ( ) ;
System. out. println ( ) ;
Person p2 = new Person ( ) ;
System. out. println ( ) ;
Person p3 = new Person ( ) ;
}
}
class Person {
String name;
int age;
static String info = "我是人类" ;
public void eat ( ) {
System. out. println ( "吃饭" ) ;
}
public static void show ( ) {
System. out. println ( "我是一个勤劳的人类" ) ;
}
public Person ( ) {
}
{
System. out. println ( "我是非静态代码块1" ) ;
System. out. println ( info) ;
show ( ) ;
System. out. println ( name) ;
eat ( ) ;
}
{
System. out. println ( "我是非静态代码块2" ) ;
}
static {
System. out. println ( "我是静态代码块1" ) ;
System. out. println ( info) ;
show ( ) ;
}
static {
System. out. println ( "我是静态代码块2" ) ;
}
}
class Root {
static {
System. out. println ( "Root的静态初始化块" ) ;
}
{
System. out. println ( "Root的普通初始化块" ) ;
}
public Root ( ) {
System. out. println ( "Root的无参数的构造器" ) ;
}
}
class Mid extends Root {
static {
System. out. println ( "Mid的静态初始化块" ) ;
}
{
System. out. println ( "Mid的普通初始化块" ) ;
}
public Mid ( ) {
System. out. println ( "Mid的无参数的构造器" ) ;
}
public Mid ( String msg) {
this ( ) ;
System. out. println ( "Mid的带参数构造器,其参数值:"
+ msg) ;
}
}
class Leaf extends Mid {
static {
System. out. println ( "Leaf的静态初始化块" ) ;
}
{
System. out. println ( "Leaf的普通初始化块" ) ;
}
public Leaf ( ) {
super ( "尚硅谷" ) ;
System. out. println ( "Leaf的构造器" ) ;
}
}
public class LeafTest {
public static void main ( String[ ] args) {
new Leaf ( ) ;
System. out. println ( ) ;
new Leaf ( ) ;
}
}
5:属性赋值
public class OrderTest {
public static void main ( String[ ] args) {
Order order = new Order ( 2 ) ;
System. out. println ( order. orderId) ;
System. out. println ( order. orderName) ;
}
}
class Order {
int orderId;
{
orderId = 1 ;
orderName = "order_BB" ;
}
String orderName = "order_AA" ;
public Order ( int orderId) {
this . orderId = orderId;
}
}
6:final
public class FinalTest {
final int MY_NUM1 = 0 ;
final int NUM2 ;
final int NUM3;
{
NUM2 = 1 ;
}
public FinalTest ( ) {
NUM3 = 2 ;
}
public FinalTest ( String info) {
this ( ) ;
}
public void method ( ) {
final int num;
num = 1 ;
System. out. println ( num) ;
}
public void method1 ( final int num) {
}
}
class C {
public void method ( ) {
}
}
class D extends C {
}
import java.util.Scanner;
import java.util.Vector;
/**
* 利用Vector代替数组处理:从键盘读入学生成绩(以负数代表输入结束),找出最高分,并输出学生成绩等级。
* 提示:数组一旦创建,长度就固定不变,所以在创建数组前就需要知道它的长度。而向量类java.util.Vector可以根据需要动态伸缩。
* 创建Vector对象:Vector v=new Vector();
* 给向量添加元素:v.addElement(Object obj); //obj必须是对象
* 取出向量中的元素:Object obj=v.elementAt(0);
* 注意第一个元素的下标是0,返回值是Object类型的。
* 计算向量的长度:v.size();
* 若与最高分相差10分内:A等;20分内:B等;
* 30分内:C等;其它:D等
*
* @author Begonia_sea
* @create 2020-07-08
*/
public class ScoreTest {
public static void main(String[] args) {
//1. 实例化Vector对象,用于存放学生成绩
Vector v = new Vector();
//2. 实例化Scanner对象,便于从键盘获取学生成绩
Scanner scanner = new Scanner(System.in);
//定义最高分的变量
int maxScore = 0;
//3. 根据提示,通过循环从键盘获取学生成绩,并保存在Vector中
for(;;){
System.out.print("请输入学生成绩:");
int score = scanner.nextInt();
//判断退出的条件
if(score < 0){
break;
}
// v.addElement(new Integer(score));//jdk5.0之前
v.addElement(score);//jdk5.0之后:自动装箱
//4. 获取学生的最高分
if(maxScore < score){
maxScore = score;
}
}
//5. 遍历学生成绩,获取各个学生的成绩和等级
for(int i = 0;i < v.size();i++){
int score = (int) v.elementAt(i);
char grade;
if(maxScore - score <= 10){
grade = 'A';
}else if (maxScore - score <= 20){
grade = 'B';
}else if(maxScore - score <= 30){
grade = 'C';
}else{
grade = 'D';
}
System.out.println("学生" + i + "成绩为:" + score + ",等级为:" + grade);
}
}
}