当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用。我们有时候希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份,例如所有的中国人都有个国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中都单独分配一个用于代表国家名称的变量。
1.static:静态的
2.static可以用来修饰属性、方法、代码块、内部类
3.使用static修饰属性:静态变量(类变量)
3.1属性:按照是否使用static修饰,又分为静态属性vs非静态属性(实例变量)
实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性,当修改其中一个对象的非静态属性时,不会导致其它对象中同样的属性值的修改
静态对象:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态变量时,会导致其它对象调用此静态变量,时修改过了的
3.2static修饰属性的其它说明
①静态变量随着类的加载而加载,可以通过"类.静态变量"的方式进行调用
类名.静态变量名
②静态变量的加载要早于对象的创建
③由于类只会加载一次,则静态变量在内存中也只会存在一份:存在方法区的静态域中
④ 类变量 实例变量
类 yes no(没有对象时不能调实例变量)
对象 yes yes
3.3静态属性举例:
System.out;
Math.PI;
3.4内存分析
4.使用static修饰方法:静态方法
①随着类的加载而加载,仍然可以通过"类.方法"来调用
② 静态方法 非静态方法
类 yes no
对象 yes yes
③静态方法中只能调用静态的方法或属性(生命周期不同)
非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性
5.static注意点:
5.1在静态的方法内,不能使用this关键字,super关键字
5.2关于静态属性和静态方法的使用,从生命周期的角度去理解
6.开发中,如何确定一个属性是否要声明为一个static?
>属性是可以被多个对象所共享的,不会随着对象的不同而不同的
>类中的常量也常常声明为static
开发中,如何确定一个方法是否要声明为一个static?
>操作静态属性的方法通常设置为静态的
>工具类中的方法习惯上声明为static的(不用造对象了)
例如:
Math、Arrays、Collections等工具类
public class Account {private int id; //账号private String password="000000"; //密码private double balance; //余额private static double interest; //利率private static double min_balance=1.0; //最小余额private static int init=10000; //账号生成的初始值//账号自动生成,即每创建一个对象时(用一次构造器),此时由于内存中只存了一个init因此它的值是一直在的(会被保存下来)public Account() {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 double getBalance() {return balance;}public void setBalance(double balance) {this.balance = balance;}public int getId() {return id;}
}
public class AccountTest {public static void main(String[] args) {Account a1=new Account("123456", 2000);Account a2=new Account("520520", 8000);Account a3=new Account("666666", 6000);System.out.println("a1的id是:"+a1.getId()+"\ta1的余额是:"+a1.getBalance());System.out.println("a2的id是:"+a2.getId()+"\ta2的余额是:"+a2.getBalance());System.out.println("a3的id是:"+a3.getId()+"\ta3的余额是:"+a3.getBalance());}
}
运行结果如下:
设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模免去我们自己再思考和摸索。式就像是经典的棋谱,不同的棋局,我们用不同的棋 谱,”套路”
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。如果我们要让类在一个虚拟机中只能产生一个对象,我们首先必须将类的构造器的访问权限设置为private,这样,就不能用new操作符在类的外部产生类的对象了,但在类内部仍可以产生该类的对象。因为在类的外部开始还无法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的。
1.所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例
2.如何实现?
懒汉式vs饿汉式
public class SingletonTest1 {public static void main(String[] args) {Bank bank1=Bank.getInstance();Bank bank2=Bank.getInstance();System.out.println(bank1==bank2); //这两者是同一个对象(地址相同)}
}
//饿汉式:已经将对象给造好了,能直接使用
class Bank{//1.私有化类的构造器private Bank() {}//2.创建内部类对象//4.要求此对象也必须声明为静态的private static Bank instance=new Bank();//3.提供公共的方法,返回类的对象public static Bank getInstance() {return instance;}
}
public class SingletonTest2 {public static void main(String[] args) {Order o1=Order.getInstance();Order o2=Order.getInstance();System.out.println(o1==o2);}
}
//懒汉式:不用造对象时就没有new对象
class Order{//1.私有化类的构造器private Order() {}//2.声明当前类对象,没有初始化//4.此对象也必须声明为static的private static Order instance=null;//3.声明public、static的返回当前类对象的方法public static Order getInstance() {if(instance==null) {instance=new Order();}return instance;}
}
3.区分懒汉式和饿汉式
饿汉式:对象加载时间过长
好处:饿汉式是线程安全的
懒汉式:延迟对象的创建
坏处:线程是不安全的
1.网站的计数器,一般也是单例模式实现,否则难以同步。
2.应用程序的日志应用,一般都使用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
3.数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。项目中,读取配置文件的类,一般也只有一个对象。没有必要每次使用配置文件数据,都生成一个对象去读取。
4.Application也是单例的典型应用
5.Windows的Task Manager(任务管理器)就是很典型的单例模式
6.Windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。
public static void main(String[] args)
1.main()方法作为程序的入口
2.main()方法也是一个普通的静态方法
3.main()方法可以作为我们与控制台交互的方式(之前用的是Scanner)
我们前面涉及到类的三个成员:属性、方法、构造器
1.代码块的所用:用来初始化类、对象
2.代码块如果有修饰的话,只能使用static
3.分类:静态代码块和非静态代码块
//static的代码块
static{}
//非static的代码块
{}
4.静态代码块
①内部可以有输出语句,随着类的加载而执行
②只执行一次(类没有重新加载就不会再执行)
③作用:初始化类的信息
④如果类中定义了多个静态代码块,则按照声明的先后顺序执行
⑤静态代码块比非静态先执行
⑥静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的
5.非静态代码块
①内部可以有输出语句,随着类的创建而执行
②每创建一个对象,就执行一次非静态代码块
③作用:可以在创建对象时,对对象的属性等进行初始化
④如果类中定义了多个静态代码块,则按照声明的先后顺序执行
⑤非静态代码块内可以调用静态的属性、静态的方法,胡非静态的属性、非静态的方法(已经生成)
对属性可以赋值的位置:
①默认初始化
②显式初始化
③构造器中初始化
④有了对象以后可以通过"对象.属性","对象.方法",进行赋值
⑤在代码块中赋值
属性为:①------>②/⑤------>③------>④
final:最终的
1.final可以用来修饰的结构:类、方法、变量
2.final用来修饰一个类:次类不能被其它类所继承
比如:String类、System类、StringBuffer类
3.final用来修饰方法:表面此方法不可以被重写
比如:Object类中getClass();
4.final用来修饰变量:此时的”变量“就称为是一个常量
4.1final用来修饰属性,可以考虑的赋值位置有:显式初始化、代码块中初始化、构造器中初始化
final int WIDTH=10; //相当于C语言中的define
多个对象有同一个属性且值一样:显式初始化
多个对象有同一个属性但值不一样:构造器中初始化
4.2final修饰局部变量
尤其是用final来修饰形参时,表面此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参。一旦赋值以后,就只能在此方法体内使用此形参,但不能进行重新赋值
static final用来修饰属性——全局常量
随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类。
abstract关键字的使用
1.abstract:抽象的
2.abstract可以用来修饰的结构:类、方法
3.abstract修饰类——抽象类
>此类不能实例化(不能造对象了)
>抽象类中一定有构造器(只要是类就有构造器),便于子类实例化时调用(子类对象实例化全过程)
>开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作
4.abstract修饰方法:抽象方法
>抽象方法只有方法的声明,没有方法体
>包含抽象方法的类,一定是一个抽象类;反之,抽象类中不一定有抽象方法
【解释】:方法有方法体就要被调用,而该方法没有方法体就不会被调用,而调用时是通过对象来调用方法的,由此可知抽象方法体不能造对象来调用它,因此这就是一个抽象类了
>若子类重写了父类中的抽象方法,则此子类方可实例化
>若子类没有重写父类中的所有抽象方法,则此子类仍然是一个抽象类,需要使用abstract来修饰
一方面,有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果
另一方面,有时必须从几个类中抽取出一些共同的行为特征,而它们之间没有is-a的关系,仅仅是具有相同的行为特征而已。例如:鼠标、键盘、打印机、扫描仪、摄像头、充电器、MP3机、手机、数码相机、移动硬盘等都支持USB连接;但它们都不属于USB
接口的使用
1.接口使用interface来定义
2.java中,接口和类是并列的两个结构
3.如何定义接口:定义接口中的成员
3.1JDK及以前:只能定义全局常量和抽象方法
>全局常量:public static final的(但书写时可以省略不写)
>抽象方法:public abstract的
interface Flyable{//全局常量public static final int MAX_SPEED=7900; //第一宇宙速度int MIN_SPEED=1; //省略了public static final
}
4.接口中不能定义构造器——说明接口不能被实例化
5.Java开发中,接口都通过让类去实现(implements)的方式来使用
如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化
如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类
6.Java类可以实现多个接口------->可以弥补java单继承性的缺陷
格式:
class AA extends BB implements CC,DD,EE
7.接口和类间的关系:实现;类和类之间:继承;接口和接口之间:继承
接口和接口之间可以继承,而且可以多继承
interface AA{void method1();
}
interface BB{void method2();
}
interface CC extends AA,BB{}
8.接口的具体使用,能体现多态性;接口实际上可以看做是一种规范
public class USBTest {public static void main(String[] args) {Computer com = new Computer();// 1.创建了接口的非匿名实现类的非匿名对象Flash flash = new Flash();com.transferData(flash);// 2.创建了接口的非匿名实现类的匿名对象com.transferData(new Printer());// 3.创建了接口的匿名实现类的非匿名对象USB phone = new USB() {@Overridepublic void start() {System.out.println("手机开始工作");}@Overridepublic void stop() {System.out.println("手机结束工作");}};com.transferData(phone);//4.创建了接口的匿名实现类的匿名对象com.transferData(new USB() {@Overridepublic void start() {System.out.println("mp3开始工作");}@Overridepublic void stop() {System.out.println("mp3停止工作");}});}
}class Computer {public void transferData(USB usb) {usb.start();System.out.println("具体传输数据的细节");usb.stop();}
}interface USB {// 常量:定义了长、宽、最大最小的传输速度void start();void stop();
}//实现类
class Flash implements USB {@Overridepublic void start() {System.out.println("U盘开始工作");}@Overridepublic void stop() {System.out.println("U盘停止工作");}
}class Printer implements USB {@Overridepublic void start() {System.out.println("打印机开启工作");}@Overridepublic void stop() {System.out.println("打印机停止工作");}
}
运行结果如下:
类的内部成员之五:内部类
1.java中允许将一个类声明在另一个类B中,则类A就是内部类,类B称为外部类
2.内部类的分类:成员内部类(静态和非静态) vs 局部内部类(方法内、代码块内、构造器内)
class Person{//静态成员内部类static class Dog{}//非静态成员内部类class Bird{}public void method() {//局部内部类class AA{}class BB{}class CC{}}
}
3.成员内部类:
①一方面,作为外部类的成员
>调用外部类的结构
>可以被static修饰
>可以被四种不同的权限修饰符修饰
②另一方面,作为一个类
>类内可以定义属性、方法、构造器等
>可以被final修饰,表示此类不能被继承。言外之意,不使用final,就可以被继承
>可以被abstract修饰,表明类不能被实例化,称为抽象类
class Person{String name;int age;public void eat() {System.out.println("人吃饭");}//静态成员内部类static class Dog{String name;int age;public void show() {System.out.println("卡拉是条狗");}}//非静态成员内部类class Bird{//属性String name;//构造器public Bird() {}//方法public void sing() {System.out.println("我是一只小小鸟");Person.this.eat(); //调用外部类的属性}}public void method() {//局部内部类class AA{}class BB{}class CC{}}
}
4.关注以下3个问题:
①如何实例化成员内部类的对象
public class InnerClassTest {public static void main(String[] args) {//创建静态的成员内部类:Dog实例Person.Dog dog=new Person.Dog();dog.show();//创建非静态的成员内部类:Bird实例//本质:有了对象通过对象来调它内部的结构Person p=new Person();Person.Bird bird=p.new Bird();bird.sing();}
}
②如何在成员内部类中区分调用外部类的结构
class Bird{//属性String name;//构造器public Bird() {}//方法public void sing() {System.out.println("我是一只小小鸟");Person.this.eat(); //调用外部类的属性}public void display(String name) {System.out.println(name); //方法的形参System.out.println(this.name); //内部类的属性System.out.println(Person.this.name); //外部类的属性}}
③开发中局部内部类的使用