目录
一、static关键字
当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上 的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象, 其方法才可以供外部调用。我们有时候希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份,就用类变量。
类属性、类方法的设计思想
类属性作为该类各个对象之间共享的变量。在设计类时,分析那些属性不因对象的改变而改变,将这些属性设置为类属性。相应的方法设置为类方法。
如果方法与调用者关,则这样的方法通常被声明为类方法,由于不需要创建对象就可以调用类方法,从而简化了方法的调用。
适用范围
在java类中,可以用static修饰属性、方法、代码块、内部类
特点
被修饰后的成员具有如下特点:
1、随着类的加载而加载
2、优先于对象的创建
3、修饰类的成员,被所有对象所共享
4、访问权限允许时,可以不创建对象,直接被类调用
关于静态方法和静态变量的使用,都可以从生命周期的角度去解释
static修饰变量
变量按照是否使用static修饰,分为静态变量和非静态变量(实例变量)。
静态变量
如果创建了当一个类的多个对象,多个对象共享同一个静态变量,当通过某一个对象去修改静态变量的值时,会导致其余所有对象调用此对变量时,该变量值是修改过的。
非静态变量(实例变量)
如果创建了类的多个对象。每个对象都独立拥有一套类的非静态属性,当修改一个对象的非静态属性时,其余对象中该变量的属性值不会被修改
说明
1、静态变随着类的加载而加载,可以通过“类名.静态变量”进行调用
2、静态变量加载早于对象的加载
3、由于类只会加载一次,则静态变量也只有一份,存在方法区的静态域中
4、静态变量和可以通过类和对象来调用;非静态变量只能通过对象来调用。
如何判断一个属性是否要声明为static的?
1、属性可以被对个对象所共享的,不会随着对象的改变而改变
2、类中的常量通常也声明为static
static修饰方法
被static修饰的方法称为静态方法
1、静态方法随着类的加载而加载,可以通过“类名.方法名”进行调用
2、静态方法中只能调用静态的方法或属性(生命周期相同),不能访问类的非静态的结构;非静态方法中,即可调用静态方法或属性,也可调用非静态方法或属性
3、静态方法可以通过类和对象来调用,非静态方法只能通过对象来调用。
4、在静态方法中,不能使用this、super关键字
如何判断一个方法是否要声明为static的?
1、操作静态属性的方法,通常设为static的
2、工具类中的方法习惯上声明为static的
练习
编写一个类实现银行账户的概念,包含的属性有“帐号”、“密码”、“存款余额”、“利率”、“最小余额”,定义封装这些属性的方法。账号要自动生成。
编写主类,使用银行账户类,输入、输出2个储户的上述信息。
public class AccountTest {
public static void main(String[] args) {
Account account1=new Account();
Account account2=new Account();
account1.setPassWord("12345689");
account1.setBalance(2000);
account2.setPassWord("987654321");
account2.setBalance(3000);
System.out.println("账户"+account1.getId()+"的密码是"+
account1.getPassWord()+"存款余额是"+account1.getBalance()+
"利率为"+Account.getRate()+"最小余额为"+Account.getMinBalance());
System.out.println("账户"+account2.getId()+"的密码是"+
account2.getPassWord()+"存款余额是"+account2.getBalance()+
"利率为"+Account.getRate()+"最小余额为"+Account.getMinBalance());
}
}
class Account{
private int id;
private String passWord;
private double balance;
private static int init=1;//用于自动生成账户使用
private static double rate=2;
private static double minBalance=2000;
public Account() {
id=init++;
}
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 int getId() {
return id;
}
public static double getRate() {
return rate;
}
public static double getMinBalance() {
return minBalance;
}
}
运行结果如下:
单例设计模式
设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、 以及解决问题的思考方式。设计模免去我们自己再思考和摸索。
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。如果我们要让类在一个虚拟机中只能产生一个对象,我们首先必须将类的构造器的访问权限设置为private,这样就不能用new操作符在类的外部产生类的对象了,但在类内部仍可以产生该类的对象。因为在类的外部开始还无法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象, 静态方法只能访问类中的静态成员变量,所以指向类内部产生的该类对象的变量也必须定义成静态的。
饿汉式
public class Singleton1 {
public static void main(String[] args) {
Singleton1 ton1=Singleton1.method();
}
private Singleton1() {
}
private static Singleton1 sin1=new Singleton1();
public static Singleton1 method() {
return sin1;
}
}
懒汉式
//懒汉式(线程不安全)
public class Singleton2 {
public static void main(String[] args) {
Singleton2 ton2=Singleton2.method2();
}
private Singleton2() {
}
private static Singleton2 sin2=null;
public static synchronized Singleton2 method2() {
if (sin2==null) {
sin2=new Singleton2();
}
return sin2;
}
}
区别饿汉式和懒汉式
饿汉式:
饿汉式是线程安全的;但对象加载时间过长
懒汉式:
懒汉式延迟了对象加载的时间。
单例模式的优点
由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。
二、理解main()方法的语法
由于Java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是 public,又因为Java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static的,该方法接收一个String类型的数组参数,该数组中保存执行Java命令时传递给所运行的类的参数。
又因为main() 方法是静态的,不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员。
main()方法也可以作为我们与控制台交互的方式
三、代码块
在java中用一对“{}”括起来的代码我们称之为代码块(初始化块)。
代码块的作用:对Java类或对象进行初始化
代码块的分类:一个类中的代码块如果有修饰符,则只能被static修饰,称为静态代码块;没有static修饰的,则称为非静态代码块。
静态代码块
作用
static代码块通常用于初始化static的属性
eg:
class Person {
public static int total;
static {
total = 100;//为total赋初值
}
…… //其它属性或方法声明
}
说明
1、静态代码块内部可以有输出语句;
2、静态代码块随着类的加载而执行
3、只会执行一次,只要当前类只加载一次,就不会重新执行
4、不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。
5、可以定义多个静态代码块,这些静态代码块代码块执行的顺序按照定义的先后顺序执行
6、静态代码块执行的顺序优先于非静态代码块执行的顺序
非静态代码块
作用
可以在创建的时候初始化对象的属性等
eg:
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);
}
}
说明
1、非静态代码块中可以有输出语句
2、非静态代码块随着对象的创建而执行
3、非静态代码块每创建一个对象,就执行一次非静态代码块
4、非静态代码块可以调用静态属性、静态方法或非静态属性、非静态方法
5、非静态代码块可以定义对个,这些非静态代码块代码块执行的顺序按照定义的先后顺序执行
四、对属性赋值的位置
1、默认初始化
2、显示初始化
3、在代码块中初始化
4、在构造器中初始化
5、有了对象以后,可以通过“对象.属性”或“对象.方法”的方式进行赋值
说明:
对属性赋值的顺序:1-->2/3-->4-->5;其中2和3按声明的先后顺序进行区分
五、final关键字
在java中声明类、变量和方法时,可以使用关键字final来修饰,表示“最终的”
final修饰类
被final类修饰的类不能被其他类所继承(eg:String类、System类、StringBuffer类)
子类可以理解为是对父类功能的一个拓展,而被final修饰的类可以理解为是“最终的类”,不能对这个类做任何改变,因此final修饰的类不能再被继承
final修饰方法
被final修饰的方法不能被重写(eg:Object类中的getClass类)
final修饰变量
被final修饰的变量(成员变量或局部变量)即称为常量。名称大写,且只能被赋值一次。
final修饰属性(成员变量)
可以final修饰的属性赋值的位置有:
1、显示初始化
2、在代码块中赋值
3、构造器中
static final用来修饰属性,表示全局常量
final修饰局部变量
特别的,当final修饰形参时,表明此形参是一个常量,给常量性附一个实参,一旦被赋值以后就,就只能在方法体中使用此参数,但不能进行修改。