目录
关键字:static
类属性、类方法的设计思想
类变量(class Variable)
静态变量的内存解析
类方法(class method)
单例 (Singleton)设计模式
理解main方法的语法
代码块
关键字:final
总结
当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用。我们有时候希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份,例如所有的中国人都有个国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中 都单独分配一个用于代表国家名称的变量
Circle类中的变量radius是一个实例变量(instance variable),它属于类的每一个对象,不能被同一个类的不同对象所共享。 上例中c1的radius独立于c2的radius,存储在不同的空间。c1中的radius 变化不会影响c2的radius,反之亦然。 如果想让一个类的所有实例共享数据,就用类变量!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
类属性作为该类各个对象之间共享的变量。在设计类时,分析哪些属性不因对象的不同而改变,将这些属性设置为类属性。相应 的方法设置为类方法。
如果方法与调用者无关,则这样的方法通常被声明为类方法,由于不需要创建对象就可以调用类方法,从而简化了方法的调用。
使用范围: 在Java类中,可用static修饰属性、方法、代码块、内部类 修饰后的成员具备以下特点类变量(类属性)由该类的所有实例共享
public class Person {private int id;public static int total = 0;public Person() {total++;id = total;}
}
public static void main(String args[]){Person Tom=new Person();Tom.id=0;total=100; // 不用创建对象就可以访问静态成员}
}
public class StaticDemo {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 Person {private int id;private static int total = 0;public static int getTotalPerson() { //id++; //非法return total;}public Person() {total++;id = total;}}
public class PersonTest {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方法内部不能有this。(也不能有super ? YES!) static修饰的方法不能被重写
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 PersonTest {public static void main(String[] args) {Person.setTotalPerson(3);
} }
设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、 以及解决问题的思考方式。设计模免去我们自己再思考和摸索。就像是经典 的棋谱,不同的棋局,我们用不同的棋谱。”套路”
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对 某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。 如果我们要让类在一个虚拟机中只能产生一个对象,
我们首先必须将类的构造器的访问权限设置为private,这样,就不能用new操作符在类的外部产生类的对象了,但在类内部仍可以产生该类的对象。因为在类的外部开始还无 法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的。
饿汉式
class Singleton {// 1.私有化构造器private Singleton() {}// 2.内部提供一个当前类的实例// 4.此实例也必须静态化
private static Singleton single = new Singleton();// 3.提供公共的静态的方法,返回当前类的对象public static Singleton getInstance() {return single;}
}
懒汉式 class Singleton {
// 1.私有化构造器private Singleton() {}
// 2.内部提供一个当前类的实例
// 4.此实例也必须静态化
private static Singleton single;// 3.提供公共的静态的方法,返回当前类的对象public static Singleton getInstance() {if(single == null) {single = new Singleton();}return single;}
}
由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的 产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可 以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。 -应用场景 由于Java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是 public,又因为Java虚拟机在执行main()方法时不必创建对象,所以该方法必须 是static的,该方法接收一个String类型的数组参数,该数组中保存执行Java命令时传递给所运行的类的参数。
又因为main() 方法是静态的,我们不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员,这种情 况,我们在之前的例子中多次碰到
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 “Tom" “Jerry" “Shkstart" 码块(或初始化块)的作用: 对Java类或对象进行初始化
代码块(或初始化块)的分类:
static代码块通常用于初始化static的属性
class Person {public static int total;static {total = 100;//为total赋初值}…… //其它属性或方法声明
}
静态代码块:用static 修饰的代码块 非静态代码块:没有static修饰的代码块
静态初始化块举例
class Person {public static int total;static {total = 100;System.out.println("in static block!");}
}
public class PersonTest {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
程序中成员变量赋值的执行顺序 在Java中声明类、变量和方法时,可使用关键字final来修饰,表示“最终的”。
//final修饰类 中国古代,什么人不能有后代,就可以被final声明,称为“太监类”!
final class A{
}
class B extends A{ //错误,不能被继承。
}//final修饰方法
class A {public final void print() {System.out.println("A");}
}
class B extends A {public void print() { // 错误,不能被重写。System.out.println("B");}
}// final修饰变量——常量 常量名要大写,内容不可修改。——如同古代皇帝的圣旨。class A {private final String INFO = "1"; //声明常量public void print() {//The final field A.INFO cannot be assigned//INFO = "ONE";}
}//static final:全局常量
关键字final应用举例 public final class Test {public static int totalNumber = 5;public final int ID;public Test() {ID = ++totalNumber; // 可在构造器中给final修饰的“变量”赋值}public static void main(String[] args) {Test t = new Test();System.out.println(t.ID);final int I = 10;final int J;J = 20;J = 30; // 非法}
}
package com.jyc.p2;
/*
* 一.static关键字的使用
* static可以用来修饰 属性 方法 构造器 内部类
* 使用static修饰属性 :静态变量
* 属性使用static修饰又分为静态属性(类变量) vs 非静态属性(实例变量)
* 实例变量:我们创建了类的多个对象,每个对象都有独立的一套类中的非静态属性.当修改一个对象中的
* 非静属性时,不会导致对象中同样的属性值的修改
* 静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量,当通过某一个对象修改静态变量
* 其他对象调用此静态变量时,是修改过的
* static修饰符的其他说明
* 1.静态变量随着类的加载而加载(可以通过类.静态变量的方式进行调用)
* 2.静态变量的加载要早于对象的创建
* 3.由于类只会加载一次,则静态变量在内存中也会存在一份,存在方法区的静态域中
* 4.类不可以调用实例变量
*
* 例如 System.out Math.PI
*
* 使用static修饰方法
* 1. 随着类的加载而加载,可以通过类.静态方法的方式进行调用
* 2.不能调用非静态方法
* 3.静态方法中只能调用静态的方法或属性,非静态的方法中,既可以调用非静态的方法和属性,也可以调用静态
* 的方法和属性
*
* static注意点
* 在静态的方法内不能使用this super 关键字
* 从生命周期的角度理解
* 属性是可以被多个对象共享的,不会随着对象的不同而不同
* 操作静态的方法,通常设置为static
* 工具类中的方法,习惯上声明为static 比如 Math.Arrays
*
* 二 单例设计模式
* 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,
*
* 饿汉式 vs 懒汉式
* 懒汉式 :延迟 对象的创建
* 饿汉式: 对象加载时间过长,线程安全
*
* 三 main方法的使用
* 1.mian()程序的入口
* public static void main(String[] args) {}(也是普通的静态方法)
* 也可以作为我们与控制台交互的方式
*
* 四 代码块(或者初始化)
* 1.代码块的作用 用来初始化类 对象
* 2.代码块只能使用static修饰
* 3.分类 静态代码块 vs 非静态代码块
* 5.静态代码块
* 内部可以有输出语句
* 随着类者加载而执行,而且只执行一次
* 初始化类信息
* 如果一个类中定义了多个代码块,则按照声明的先后顺序执行
* 静态代码块的执行由于非静态代码块
* 静态代码块内可以调用静态属性静态方法,不能调用非静态结构
*
* 非静态代码块
* 内部可以有输出语句
* 随着对象的创建而执行,每创建一个对象执行一次
* 作用:可以对对象的属性进行初始化
* 如果一个类中定义了多个代码块,则按照声明的先后顺序执行
* 非静态代码块可以调用静态属性,静态方法 或非静态属性 非静态方法
*
* 属性可以赋值的位置
* 1.默认初始化
* 2.显示初始化
* 3.构造器中初始化
* 4.有了对象以后 可以对象.属性 对象.方法进行初始化
* 5.代码块中赋值
* 赋值顺序 1--> 2/5--> 3 -->4
*
* 五 final关键字 最终的
* final 可以修饰的结构 类 方法 变量
*
* final修饰一个类 此类不能够在继承
* 比如 String System
*
* final修饰一个方法 表明方法不可以被重写
* 比如 object.getClass()
*
* final可以用来修饰变量 此时的变量就是常量了final修饰属性 可以考虑赋值的位置有 显示初始化 代码块中 构造器中final修饰属性 修饰局部变量尤其是final修饰形参时,表明形参是一个常量,当我们调用此方法时给常量形参赋一个实参一但赋值以后,就只能在方法体内使用形参,但不能重新赋值static final:用来修饰属性 全局常量static final:用来修饰方法 不能被继承* */
public class test1 {public static void main(String[] args) {Chinese c1=new Chinese("zs",18);Chinese c2=new Chinese("ls",22);c1.nation="中国";System.out.println(c2.nation);System.out.println("-----------单例设计模式饿汉式-------");Bank bank1=Bank.getInstance();Bank bank2=Bank.getInstance();System.out.println(bank1==bank2);System.out.println("-----------代码块-------");System.out.println(Chinese.desc);System.out.println(c2.language);}
}
class Chinese{String name;int age;String language;final int width=10;final int left;final int right;static String nation;static String desc="我是一个人";Chinese(){right=100;}Chinese( String name, int age){this.age=age;this.name=name;right=100;}public static void show(){System.out.println("show执行");//name="tom";无法从静态上下文中引用非静态 变量nation="中国";//可以调用静态结构}//代码块{System.out.println("代码块");language="汉语";show();left=100;}static {System.out.println("静态代码块");desc="我是一个中国人";show();}
}
//饿汉式class Bank{//私有化类的构造器private Bank(){}//内部创建类的对象(要求此对象必须为静态的)private static Bank instance=new Bank();//通过公共的静态对象 返回类的对象public static Bank getInstance(){return instance;}}//饿汉式class Change{private Change(){}//声明当前类对象,没有初始化private static Change instance =null;//声明public static的返回当前类对象方法public static Change getInstance(){if (instance==null){instance= new Change();}return instance;
}}// class C extends String{} 不能继承//class A{ 不能重写
// final public void show(){}
//}
//class B extends A{
// public void show(){}
//}