static 关键字

当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用
我们有时候希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份,例如所有的中国人都有个国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中都单独分配一个用于代表国家名称的变量。

class Circle {
  private double radius;
  public Circle(double radius) {
    this.radius=radius;
  }
  public double findArea() {
    return Math.PI*radius*radius;
  }
}

创建两个Circle对象
  Circle c1=new Circle(2.0); //c1.radius=2.0
  Circle c2=new Circle(3.0); //c2.radius=3.0
Circle类中的变量radius是一个实例变量(instance variable),它属于类的每一个对象,不能被同一个类的不同对象所共享。

上例中c1的radius独立于c2的radius,存储在不同的空间。c1中的radius变化不会影响c2的radius,反之亦然。

如果想让一个类的所有实例共享数据,请用类变量

在Java类中声明变量方法内部类时,可使用关键字static做为修饰符。

static标记的变量或方法由整个类(所有实例)共享,如访问控制权限允许,可不必创建该类对象而直接用类名加‘.’调用

static成员也称类成员或静态成员,如:类变量、类方法、静态方法等。

类变量(class Variable)

类变量(类属性)由该类的所有实例共享

public class Person {
  private int id;
  public static int total = 0;
  public Person() {
    total++;
    id = total;
  }
}

类属性类似于全局变量

类属性应用举例

 class Person {
  private int id;
  public static int total = 0;
4   public Person() {
  total++;
id = total;
}
public static void main(String args[]){
  Person Tom=new Person()
10     Tom.id=0;
11     total=100; // 不用创建对象就可以访问静态成员
}
} public class OtherClass {
  public static void main(String args[]) {
  Person.total = 100; // 不用创建对象就可以访问静态成员
//访问方式:类名.类属性类名.类方法
System.out.println(Person.total);
Person c = new Person();
System.out.println(c.total); //输出101
}
}

类方法(class Method)

没有对象的实例时,可以用类名.方法名()的形式访问由static标记的类方法

  class Person {
private int id;
private static int total = 0;
public static int getTotalPerson() {
return total;
}
public Person() {
total++;
id = total;
}
}
public class TestPerson {
public static void main(String[] args) {
System.out.println("Number of total is " +Person.getTotalPerson()); //没有创建对象也可以访问静态方法
Person p1 = new Person();
System.out.println( "Number of total is "+ Person.getTotalPerson());
}
}

在static方法内部只能访问类的static属性,不能访问类的非static属性

 class Person {
private int id;
private static int total = 0;
public static int getTotalPerson() {
  id++; //非法
  return total;
}
public Person() {
  total++;
  id = total;
}
}

因为不需要实例就可以访问static方法,因此static方法内部不能有this(也不能有super)

 class Person {
  private int id;
private static int total = 0;
public static void setTotalPerson(int total){
this.total=total; //非法,在static方法中不能有this,也不能有super
}
public Person() {
total++;
id = total;
}
}
public class TestPerson {
public static void main(String[] args) {
  Person.setTotalPerson();
}
}

在静态方法里只能直接调用同类中其它的静态成员(包括变量和方法),而不能直接访问类中的非静态成员。这是因为,对于非静态的方法和变量,需要先创建类的实例对象后才可使用,而静态方法在使用前不用创建任何对象

静态方法不能以任何方式引用this和super关键字。与上面的道理一样,因为静态方法在使用前不用创建任何实例对象,当静态方法被调用时,this所引用的对象根本就没有产生。

main() 方法是静态的,因此JVM在执行main方法时不创建main方法所在的类的实例对象,因而在main()方法中,我们不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员,这种情况,我们在以后的例子中会多次碰到。

类属性、类方法的设计思想

类属性作为该类各个对象之间共享的变量。在设计类时,分析哪些类属性不因对象的不同而改变,将这些属性设置为类属性。相应的方法设置为类方法

如果方法与调用者无关,则这样的方法通常被声明为类方法,由于不需要创建对象就可以调用类方法,从而简化了方法的调用

练习

1、编写一个类,实现银行账户的概念,包含的属性有“帐号”、“密码”、“存款余额”、“利率”、“最小余额”,定义封装这些属性的方法。账号要自动生成。
编写主类,使用银行账户类,输入、输出3个储户的上述信息。
考虑:哪些属性可以设计成static属性。

 /**
* 编写一个类,实现银行账户的概念,包含的属性有“帐号”、“密码”、“存款余额”、“利率”、“最小余额”,定义封装这些
* 属性的方法。账号要自动生成。
*/
public class Account { //初始化的 id
private static int initId = 1000; //账号
private String id; //密码
private String password; //余额
private int balance; //利率
private static double rate; //最小余额
private static int minBalance; public Account(String password, int balance) {
this.id = "" + (initId++);
this.password = password;
this.balance = balance;
} public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public int getBalance() {
return balance;
} public void setBalance(int balance) {
this.balance = balance;
} public static double getRate() {
return rate;
} public static void setRate(double rate) {
Account.rate = rate;
} public static int getMinBalance() {
return minBalance;
} public static void setMinBalance(int minBalance) {
Account.minBalance = minBalance;
} @Override
public String toString() {
return "Account [id=" + id + ", password=" + password + ", balance="
+ balance + ", rate=" + rate + ", minBalance=" + minBalance + "]";
}
}
 /**
* 编写主类,使用银行账户类,输入、输出3个储户的上述信息。
*/
public class TestBank {
public static void main(String[] args) { //统一设置 rate 和 minBalance
Account.setMinBalance(100);
Account.setRate(0.01); Account acc1 = new Account("1234", 100);
Account acc2 = new Account("1235", 200);
Account acc3 = new Account("1236", 300); System.out.println(acc1);
System.out.println(acc2);
System.out.println(acc3);
}
}

静态初始化

一个类中可以使用不包含在任何方法体中的静态代码块(static block ),当类被载入时,静态代码块被执行,且只被执行一次,静态块经常用来进行类属性的初始化
static块通常用于初始化static (类)属性
class Person {
  public static int total;
  static {
    total = 100;//为total赋初值
  }
  …… //其它属性或方法声明
}

静态初始化举例
class Person {
  public static int total;
  static {
    total = 100;
    System.out.println("in static block!");
  }
}

public class Test {
  public static void main(String[] args) {
    System.out.println("total = "+ Person.total);
    System.out.println("total = "+ Person.total);
  }
}

输出:
in static block
total=100
total=100


 public class Chinese {

     String name;
int age; static String country; //静态代码块: 使用 static 修饰的代码块
//在类被加载时执行一次. 且执行一次. 可以在静态代码块中对静态成员变量进行初始化.
static{
System.out.println("静态代码块");
} //非静态代码块: 先于构造器执行, 没创建一个对象都会执行一次.
{
System.out.println("非静态代码块");
} //对非静态成员进行初始化.
public Chinese(String name, int age) {
super();
this.name = name;
this.age = age; country = "";
} public Chinese() {
System.out.println("构造器");
} String getInfo(){
return "name: " + name;
} static void test(){
System.out.println("test...");
System.out.println("country: " + country); // System.out.println(name);
}
}
 /**
* static: 静态的.
* 1. 若需要一个类的多个对象共享一个变量, 则该变量需要使用 static 修饰.
* 2. 因为 static 修饰的变量为类的所有的实例所共享, 所以 static 成员不属于某个类的实例, 而属于整个类.
* 所以在访问权限允许的情况下, 可以使用 "类名." 直接访问静态成员(成员包括属性和方法)
* 3. 注意: 在静态方法里只能直接调用同类中其它的静态成员(包括变量和方法),而不能直接访问类中的非静态成员。
* 这是因为,对于非静态的方法和变量,需要先创建类的实例对象后才可使用,而静态方法在使用前不用创建任何对象。
* 4. 同 3 的道理: 静态方法不能以任何方式引用this和super关键字
* 5. 非静态方法中可以直接来访问类的静态成员.
* 6. main() 方法是静态的,因此JVM在执行main方法时不创建main方法所在的类的实例对象
*
* 7. 静态初始化指对类的静态属性进行初始化.
* 7.1 不应该在构造器中对静态成员进行初始化: 因为静态成员不因类的实例而改变.
* 7.2
* //非静态代码块: 先于构造器执行, 每创建一个对象都会执行一次.
* {
* System.out.println("非静态代码块");
* }
* 7.3
* //静态代码块: 使用 static 修饰的代码块
* //在类被加载时执行一次. 且执行一次. 可以在静态代码块中对静态成员变量进行初始化.
* //先于非静态代码块和构造器执行.
* static{
* System.out.println("静态代码块");
* } */
public class TestStatic {
public static void main(String[] args) {
Chinese.country = "中国";
Chinese.test(); Chinese p1 = new Chinese();
p1.name = "Tom";
p1.age = 12;
p1.country = "China"; Chinese p2 = new Chinese();
p2.name = "Jerry";
p2.age = 13;
// p2.country = "中国"; System.out.println(p1.name);
System.out.println(p1.country); System.out.println(p2.name);
System.out.println(p2.country); System.out.println(p1.getInfo());
}
}

单例模式

设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式就想是经典的棋谱,不同的棋局,我们用不同的棋谱,免得我们自己再去思考和摸索。

所谓类的单态设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法

如果我们要让类在一个虚拟机中只能产生一个对象,我们首先必须将类的构造方法的访问权限设置为private,这样,就不能用new 操作符在类的外部产生类的对象了,但在类内部仍可以产生该类的对象。因为在类的外部开始还无法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的。

单例 Singleton 设计模板

class Single {
  private static Single onlyone = new Single();//私有的,只能在类的内部访问
  private String name;
  public static Single getSingle() { //getSingle()为static,不用创建对象即可访问
    return onlyone;
  }
  private Single() {} //private的构造器,不能在类的外部创建该类的对象
}

public class TestSingle{
  public static void main(String args[]) {
    Single s1 = Single.getSingle(); //访问静态方法
    Single s2 = Single.getSingle();
    if (s1==s2){
      System.out.println("s1 is equals to s2!");
    }
  }
}


/**

* 设计为单子模式
*/
public class SingleInstance {

  //构造器私有化
  private SingleInstance() {}

  //在类的内部创建实例
  private static SingleInstance instance = new SingleInstance();

  //提供 get 方法
  public static SingleInstance getInstance() {
    return instance;
  }
}

/*

* 所谓类的单态设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例
*   不能在类的外部通过 new 关键字的方式创建新的实例: 构造器私有化.
*   在类的内部创建实例
*   为了让类的外部能够访问到类的内部创建的实例, 该实例必须使用 static 修饰.
*   不能允许在类的外部修改内部创建的实例的引用. SingleInstance.instance = null;
* 需要把该属性用 private 修饰
*   为了让外部进行读, 添加对应的 get 方法.
*/

// SingleInstance s1 = new SingleInstance();
// SingleInstance s2 = new SingleInstance();

SingleInstance s1 = SingleInstance.getInstance();
// SingleInstance.getInstance() = null;

SingleInstance s2 = SingleInstance.getInstance();

System.out.println(s1 == s2);

理解main方法的语法

由于Java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public,又因为java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static的,该方法接收一个String类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数。

命令行参数用法举例
public class CommandPara {
  public static void main(String[] args) {
    for ( int i = 0; i < args.length; i++ ) {
      System.out.println("args[" + i + "] = " + args[i]);
    }
  }
}

//运行程序CommandPara.java
java CommandPara lisa "bily" "Mr Brown"
//输出结果:

args[0] = lisa
args[1] = bily
args[2] = Mr Brown


if(args != null){

  if(args.length > 1){
    for(String arg: args){
      System.out.println(arg);
    }
  }
}

Run As》Run Configuration...》Arguments 输入a b c d e 》Run

这就是main方法在运行时传参

高级类特性----static关键字的更多相关文章

  1. 高级类特性----final关键字

    final 关键字 在Java中声明类.属性和方法时,可使用关键字final来修饰. final标记的变量(成员变量或局部变量)即成为常量,只能赋值一次. final标记的类不能被继承.提高安全性,提 ...

  2. Java高级类特性(二)

    一.static关键字 static关键字用来声明成员属于类,而不是属于类的对象.1). static (类)变量类变量可以被类的所有对象共享,以便与不共享的成员变量区分开来. static变量也称作 ...

  3. 2.18 C++类与static关键字

    参考:http://www.weixueyuan.net/view/6349.html 总结: 类中的成员变量或成员函数一旦与static关键字相结合,则该成员变量或成员函数就是属于类的,而不是再是属 ...

  4. Java【第八篇】面向对象之高级类特性

    static 关键字 当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用.我们有 ...

  5. Java 类和Static关键字

    类的定义 类的命名.首字母大写 大括号后面没有分号 成员变量 Java会自动初始化成员变量但是不会自动初始化局部变量: 可以在定义成员变量是直接初始化,成员变量的作用范围在整个类体 对象的创建和引用的 ...

  6. String类、static关键字、Arrays类、 Math类的一些学习心得

    String类 java.lang.String 类代表字符串.Java程序中所有的字符串文字(例如"abc" )都可以被看作是实现此类的实例. 类 String 中包括用于检查各 ...

  7. Java高级类特性(一)

    一.继承性 1)继承的使用:权限修饰符 class A extends B{}:2)子类:A 父类(基类 SuperClass):B3)子类继承父类后,父类中声明的属性.方法,子类都可以获取到明确:当 ...

  8. 高级类特性----接口(intertface)

    接 口 有时必须从几个类中派生出一个子类,继承它们所有的属性和方法.但是,Java不支持多重继承.有了接口,就可以得到多重继承的效果. 接口(interface)是抽象方法和常量值的定义的集合. 从本 ...

  9. 高级类特性----抽象类(abstract class)

    抽象类(abstract class) 随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用.类的设计应该保证父类和子类能够共享特征.有时将一个父类设计得非常抽象,以至于它没有具 ...

随机推荐

  1. jQuery图片tab栏切换

    <script> $(function(){ $('.tab li').mouseenter(function(){ var $this=$(this); var index=$this. ...

  2. GNU风格 ARM汇编语法2

    .GNU汇编程序中的标号symbol(或label) 标号只能由a-z,A-Z,-,".",_等(由点.字母.数字.下划线等组成,除局部标号外,不能以数字开头)字符组成. Symb ...

  3. JavaScript(js)文件路径字符串中丢失"\"斜线的解决方法

    在刚刚的开发过程中,遇到一个JavaScript 文件路径字符串中丢失"\"的问题,解决过程如下: 背景:cs文件中获取一段包含有路径信息的字符串,将此字符串做为参数传递给前台as ...

  4. Accumulator

    Accumulator简介 Accumulator是spark提供的累加器,顾名思义,该变量只能够增加. 只有driver能获取到Accumulator的值(使用value方法),Task只能对其做增 ...

  5. 激活JetBrains的IDE(PhpStorm、WebStorm、IntelliJ IDEA)

    JetBrains 授权服务器(License Server URL): http://idea.imsxm.com/ 转自: http://www.imsxm.com/jetbrains-licen ...

  6. C语言 · s01串

    算法训练 s01串   时间限制:1.0s   内存限制:256.0MB      问题描述 s01串初始为"0" 按以下方式变换 0变1,1变01 输入格式 1个整数(0~19) ...

  7. Linux 修改mac 地址方法记录

    Linux 修改MAC 记录: sudo ifconfig eth0 hw ether 70B3D5106F90

  8. HTML——动画效果:图片循环横向播放

    一.html <!DOCTYPE HTML> <html> <head> <title>Home</title> <link href ...

  9. Java上的jQuery?解析HTML利器—Jsoup

    也许大家有过在java运行平台上解析html的经历,通常的方式是将HTML以XML的形式进行结点解析,调用java本身的xml解析类库.这样的方式很容易理解并且很方便,但习惯用jQuery的各位是否在 ...

  10. 制作Windows Server 2008安装启动U盘

    昨天刚下了Windows server 2008因为没有刻录机,所以我就用2G U盘把Windows server 2008光盘镜像做成U盘安装效果和光盘安装一样. 下面就是制作方法: UltraIS ...