时间:2018-07-25
作者:魏文应
一、static 关键字
static 修饰类属性
用static来修饰类的成员变量,也被称为 类变量。我们可以先看下面代码:
class SportsMan{
String name;
static String nation;
@Override
public String toString() {
return "SportsMan [name=" + name + ", nation=" + nation + "]";
}
}
public class TestSprotsMan {
public static void main(String[] args){
SportsMan s1 = new SportsMan();
SportsMan s2 = new SportsMan();
s1.name = "小强";
s1.nation = "中国";
System.out.println(s1);
System.out.println(s2);
}
}
输出结果如下:
SportsMan [name=小强, nation=中国]
SportsMan [name=null, nation=中国]
你会发现,s1 和 s2 的 name 属性值不一样,而 nation 属性值是一样的。这说明,static 修饰的成员变量,在由该类创建的所有对象中,static 成员变量,只有一份。假设使用SportsMan类,创建了 s1、s2、s3、s4、s5、s6这些实例,修改任何一个实例的static成员变量,会导致 该类的所有实例 的static成员变量的值发生改变。而 没有 static 修饰 的成员变量,各自有各自的存储单元,不会发生修改实例的成员变量,导致另一个成员变量的值也被修改的情况。
这也说明了,使用 static 修饰的属性,不依赖实例 而存在,只要有类,就有它。所以可以使用 类名.属性
的形式来调用它:
SportsMan.nation = "美国";
System.out.println(SportsMan.nation);
static 修饰类方法
static 修饰的类的方法,也被称为 类方法。和static修饰的类属性一样,类方法有以下特点:
- 随着类的加载而加载。
- 内存中也是独有一份。
- 不依赖类的实例而存在,可以使用
类名.方法
的形式来调用。 - 内部可以调用 static 修饰的属性和方法。
- 内部不可以调用 没有 static 修饰的属性和方法。
下面是其应用实例:
class SportsMan{
static int name;
public void show(){
System.out.println("Show:Hello World!");
show2(); // 类内直接使用
}
public static void show2(){
System.out.println("Show2:Hello World!");
name = "魏文应";
}
}
public class TestSprotsMan {
public static void main(String[] args){
SportsMan s = new SportsMan();
s.show(); // 需要创建类的实例
SportsMan.show2(); // 外面直接调用
}
}
上面代码中,没有 static 修饰的方法 show()
只能通过 对象.方法
的方式调用,使用该方法前需要创建一个对象。而有 static 修饰的方法 show2()
不但可以使用 对象.方法
的形式调用,还可以使用 类.方法
的形式调用。
二、设计模式
什么是设计模式?就像铁匠,打了一辈子的铁,最后总结了一些经验,这些经验使得打铁更省力,打出的铁性能更好。设计模式也是一样,Java 程序员在必须大量的程序以后,发现了一些比较好的写法,并且这些写法比较常用。将这些写法总结成标准模式,就叫做设计模式。
单例设计模式
什么叫单例模式?单例模式就是有一个类,允许这个类创建一个对象 。下面是一种叫做 饿汉式 单例模式:
class Singleton{
// 1.私有化构造器,使得类的外部不能够调用此构造器。
private Singleton(){
}
// 2.在类的内部创建一个类的实例
private static Singleton instance = new Singleton();
// 3.私有化此对象,通过公共的方法来调用
public static Singleton getInstance(){
return instance;
}
}
public class TestSingleton {
public static void main(String[] args){
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2);
}
}
私有化构造器,在类内部创建当前类对象,使用 static 修饰类方法,这样,外部只能通过 类名.方法
的形式返回实例的引用。而这个实例的引用只有一个,那就是 instance
,从而达到这个类只能创建一个实例的效果。另外,还有一种叫做 懒汉式 的单例模式:
class Singleton1{
private Singleton1(){
}
private static Singleton1 instance = null;
public static Singleton1 getInstance(){
if(instance == null){
instance = new Singleton1();
}
return instance;
}
}
public class TestSingleton1 {
public static void main(String[] args){
Singleton1 s1 = Singleton1.getInstance();
Singleton1 s2 = Singleton1.getInstance();
System.out.println(s1 == s2);
}
}
懒汉模式,同样要私有化构造器,类内部在第一次使用 getInstnce 类方法 时,创建一个实例,此后不再创建新的实例。这样的好处是,在需要是在创建实例。缺点是,在多线程中,可能有多个线程进入 if(instance == null)
内部,导致 instance = new Singleton1();
语句多次被执行。
三、main()方法的使用
在类内部,main方法格式如下:
public static void main(String[] args){
}
它是程序的入口。我们可以对它进行 传参测试 :
public class TestMain {
public static void main(String[] args) {
for(int i = 0; i < args.length; i++){
System.out.println(args[i]);
}
}
}
在 Eclipse 中, 依次点击 Run As -> Run Configurations -> Arguments , 在Program Arguments 中,输入你希望向main() 中传入的参数,比如我这里 传入参数 为三个字符串:
魏文应、小强、宇航
然后点击 Run 按钮即可。
四、类变量的成员之四:初始化块
什么是初始化块?初始化块就是在一个类中, 用 { }
大括号直接括起来的内容,比如:
class Order{
{
System.out.println("我是初始化块");
}
}
在类中,关于属性的操作,顺序是:
1、先是默认的初始化。
2、显示的初始化或者代码块内初始化。
3、构造器赋值操作。
4、创建对象以后,外部调用赋值操作。
比如,下面对类的属性进行赋值操作:
class Order{
private int orderId = 1000;
// 初始化块,非静态代码块
{
orderId = 1001;
System.out.println("我是非静态代码块1");
}
{
orderId = 1002;
System.out.println("我是非静态代码块2");
}
public Order(int orderId) {
super();
this.orderId = orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
}
public class TestOrder {
public static void main(String[] args) {
Order o1 = new Order(1004);
System.out.println(o1);
}
}
首先创建了orderId成员变量,默认初始化 orderId = 0
。然后是我们代码中,显示初始化 orderId = 1000
,然后是 代码块 { }
中 orderId = 1001
,代码块可以有多个,所以在代码块2中,再次赋值 orderId = 1002
。在然后就是在 构造器中 赋值,最后可以在 外部 赋值。
注意:显式初始化和代码块,它们处于同一优先级别,也就是说,它们在类中出现的先后,是影响赋值的先后的。 比如下面代码:
class Order{
{
orderId = 1001;
}
private int orderId = 1000;
}
首先 orderId = 0
, 然后 orderId = 1001
,然后才是 orderId = 1000
。
static 静态代码块
什么是静态代码块?在类中,使用 static{ }
的代码块。比如下面代码:
class Order{
static{
System.out.println("我是静态初始化块");
}
}
静态代码块的执行,要早于非静态代码块,和在类中的位置无关。注意:静态代码块中,调用的属性和方法都需要是类方法和类属性,也就是static修饰的方法和属性 。
五、关键字 final
final 表示最终的。可以修饰 属性、方法、类。
final 修饰属性
final修饰属性时,赋值以后 值就不可以再修改,相当于常量:
final int PI = 3.141592563;
既然是常量,那么 final 修饰的成员变量,建议使用 全大写 字母命名。final 修饰的属性,必须显式的赋值。赋值还可以再 代码块、构造器中赋值,但是,赋值操作只能有一次。:
class Test{
final int PI;
{
PI = 3.141592563;
}
}
class Test{
final int PI;
public Test(){
PI = 3.141592563;
}
}
final 修饰方法
final 修饰的方法,就不能对它进行重写了:
class Test{
public final void method1(){
}
// public void method1(){
// }
}
比如上面代码,method1() 方法被 final 修饰,那么method1() 方法就 不能再进行重写 了。
final 修饰类
被final 修饰的类,就不能对它进行继承了:
final class Test{
}
那么下面的操作是 不被允许的:
class Person extends Test{
}
从上面可以看出,Test 被 final 修饰以后,就 其它类就不能去继承它。