文章目录
1. 关键字:static
why:
1.原本只有通过new关键字产生出对象,这时系统才会分配内存空间给对象, 其方法才可以供外部调用。想不用创建对象,直接类调用
2.无论创建多少对象,想让某些特定的数据在内存空间里只有一份
static:静态的,static可以用来修饰:属性、方法、代码块、内部类
1.1 static修饰属性
即静态变量(或类变量)
类的多个对象共享同一个静态变量。当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的。而非静态属性不会。
说明:
- 静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用
- 静态变量的加载要早于对象的创建。
- 由于类只会加载一次,则静态变量在内存中也只会存在一份:存在方法区的静态域中。
应用场合:
- 属性是可以被多个对象所共享的,不会随着对象的不同而不同的。
- 类中的常量也常常声明为static
1.2 static修饰方法
即静态方法
说明:
- 随着类的加载而加载,可以通过"类.静态方法"的方式进行调用
- 静态方法中,只能调用静态的方法或属性;
而非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性 - 在静态的方法内,不能使用this关键字、super关键字
调用权限 | 类变量 | 实例变量 | 类方法 | 实例方法 |
---|---|---|---|---|
类 | yes | no | yes | no |
对象 | yes | yes | yes | yes |
PS:主要从生命周期考虑,static修饰成员随类加载而加载,早于实例对象的创建。故可不创建对象,直接被类调用
应用场景:
- 操作静态属性的方法,通常设置为static的
- 工具类中的方法,习惯上声明为static的。 比如:Math、Arrays、Collections
内存解析
1.3单例设计模式
采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例。
思想:构造器的访问权限设置为private --》调用该类的某个静态方法返回内部创建的对象–》指向类内部产生的该类对象的变量也必须定义成静态的
//饿汉式 坏处:对象加载时间过长。 好处:饿汉式是线程安全的
class Bank{
//1.私有化类的构造器
private Bank(){
}
//2.内部创建类的对象
//4.要求此对象也必须声明为静态的
private static Bank instance = new Bank();
//3.提供公共的静态的方法,返回类的对象
public static Bank getInstance(){
return instance;
}
}
//懒汉式 好处:延迟对象的创建
class Order{
//1.私有化类的构造器
private Order(){
}
//2.声明当前类对象,没有初始化
//4.此对象也必须声明为static的
private static Order instance = null;
//3.声明public、static的返回当前类对象的方法
public static Order getInstance(){
if(instance==null){
synchronized(Order.class){ //静态方法内得用类作 锁
if(instance == null){
instance = new Order();
}
}
}
return instance;
}
}
2 main()方法
public static void main(String[] args) {
}
使用说明:
1.main()方法作为程序的入口(虚拟机要调用,故权限为public)
2.main()方法是静态方法(故虚拟机执行main()方法时不必创建对象)
3.main()方法可以作为我们与控制台交互的方式(String类型的数组参数,保存执行Java命令时传递给所运行的类的参数)
传参方式1:java 字节码文件名 参数1 参数2 …
传参方式2:Run->Edit Configuration:“1” "2"选择传参的位置 "3"为传入的字符串参数,空格隔开
3.代码块
代码块如果有修饰的话,只能使用static.即静态代码块
VS | 静态代码块 | 非静态代码块 |
---|---|---|
作用 | 初始化类的信息 | 可对对象的属性等进行初始化 |
执行 | 随类加载而执行,且只执行一次 | 随对象的创建而执行,每创建一次就执行一次 |
执行顺序 | 由父及子静态先行,声明先后 | 同 |
调用 | 静态的属性、静态的方法 | 静态and非静态的属性方法 |
- 对属性可以赋值的位置及执行先后顺序:
①默认初始化
②显式初始化/⑤在代码块中赋值
③构造器中初始化
④有了对象以后,可以通过"对象.属性"或"对象.方法"的方式,进行赋值
4.关键字:final
final:最终的
- final可以用来修饰的结构:类、方法、变量
- final 用来修饰一个类:此类不能被其他类所继承。比如:String类、System类、StringBuffer类
- final 用来修饰方法:表明此方法不可被重写。比如:Object类中getClass();
- final 用来修饰变量:此时的"变量"就称为是一个常量
①final修饰属性:可赋值的位置有:显式初始化、代码块中初始化、构造器中初始化,否则不能用
②final修饰局部变量:尤其是使用final修饰形参时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参。一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值。
- static final 用来修饰属性:全局常量
5.抽象类与抽象方法
抽象方法:声明一个方法但不提供实现,该方法的实现由子类提供。
抽象类:有时将一个父类设计得非常抽象(时常含抽象方法),以至于它没有具体的实例。
5.1关键字:abstract
abstract:抽象的
- abstract可以用来修饰的结构:类、方法
- abstract修饰类:抽象类
格式:abstract class A{ }
①此类不能实例化
②抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全过程)
③开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作 - abstract修饰方法:抽象方法
格式:权限修饰 abstract 方法名();
①抽象方法只有方法的声明,没有方法体
②包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法的。
③若子类重写了父类中的所有的抽象方法后,此子类方可实例化;否则此子类也是一个抽象类,需要使用abstract修饰
PS:abstract不能用来修饰(从是否可以被重写的角度考虑:属性、构造器、私有方法、静态方法、final的方法、final的类(不能继承
5.2模板方法设计模式
在软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现。
//抽象类的应用:模板方法的设计模式
public class TemplateMethodTest {
public static void main(String[] args) {
BankTemplateMethod btm = new DrawMoney();
btm.process();
BankTemplateMethod btm2 = new ManageMoney();
btm2.process();
}
}
abstract class BankTemplateMethod {
// 具体方法
public void takeNumber() {
System.out.println("取号排队");
}
public abstract void transact(); // 办理具体的业务 //钩子方法
public void evaluate() {
System.out.println("反馈评分");
}
// 模板方法,把基本操作组合到一起,子类一般不能重写
public final void process() {
this.takeNumber();
this.transact();// 像个钩子,具体执行时,挂哪个子类,就执行哪个子类的实现代码
this.evaluate();
}
}
class DrawMoney extends BankTemplateMethod {
public void transact() {
System.out.println("我要取款!!!");
}
}
class ManageMoney extends BankTemplateMethod {
public void transact() {
System.out.println("我要理财!我这里有2000万美元!!");
}
}
6.接口(interface)
接口,实际上可以看做是一种规范。接口实现则是 "能不能"的关系,而继承是一个"是不是"的关系
- Java中,接口和类是并列的两个结构
- 接口中无构造器!意味着接口不可以实例化
- JDK7及以前:只能定义全局常量和抽象方法
①全局常量:默认是由public static final修饰的
②抽象方法:默认是由public abstract修饰的 - JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法(这default不能缺省
①接口中定义的静态方法,只能通过接口来调用。
②接口中的默认方法:实现类的对象调用,若实现类重写了该方法,则调用重写
实现类实现多个接口,而这多个接口中定义了同名同参数的默认方法。若实现类没重写则接口冲突
子类(实现类)继承的父类和实现的接口中声明了同名同参数的默认方法,类优先原则。但声明同名成员变量则需指定调用(同方法指定见程序
interface Filial {// 孝顺的
default void help() {
System.out.println("老妈,我来救你了");
}
}
interface Spoony {// 痴情的
default void help() {
System.out.println("媳妇,别怕,我来了");
}
}
class Father{
public void help(){
System.out.println("儿子,就我媳妇!");
}
}
class Man extends Father implements Filial, Spoony {
@Override
public void help() {
System.out.println("我该就谁呢?");
}
public void Choice{
help(); //重写的方法
super.help(); //调用父类方法
Filial.super.help(); //调用接口的默认方法
Spoony.super.help(); //调用接口的默认方法
}
}
- Java开发中,接口通过让类去实现(implements)的方式来使用. 具体使用体现多态性
①如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化;否则此实现类仍为一个抽象类 - Java类可以实现多个接口 —>弥补了Java单继承性的局限性
格式:class AA extends BB implements CC,DD,EE{ } - 接口与接口之间可以继承,而且可以多继承
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(){
@Override
public void start() {
System.out.println("手机开始工作");
}
@Override
public void stop() {
System.out.println("手机结束工作");
}
};
com.transferData(phone);
//4. 创建了接口的匿名实现类的匿名对象
com.transferData(new USB(){
@Override
public void start() {
System.out.println("mp3开始工作");
}
@Override
public void stop() {
System.out.println("mp3结束工作");
}
});
}
}
class Computer{
public void transferData(USB usb){//USB usb = new Flash();
usb.start();
System.out.println("具体传输数据的细节");
usb.stop();
}
}
interface USB{
//常量:定义了长、宽、最大最小的传输速度等
void start();
void stop();
}
class Flash implements USB{
@Override
public void start() {
System.out.println("U盘开启工作");
}
@Override
public void stop() {
System.out.println("U盘结束工作");
}
}
class Printer implements USB{
@Override
public void start() {
System.out.println("打印机开启工作");
}
@Override
public void stop() {
System.out.println("打印机结束工作");
}
}
6.1代理模式
代理设计就是为其它对象提供一种代理以控制对这个对象的访问。
应用场景:
- 安全代理:屏蔽对真实角色的直接访问。
- 远程代理:通过代理类处理远程方法调用(RMI)
- 延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象
public class NetWorkTest {
public static void main(String[] args) {
Server server = new Server();
// server.browse();
ProxyServer proxyServer = new ProxyServer(server);
proxyServer.browse();
}
}
interface NetWork{
public void browse();
}
//被代理类
class Server implements NetWork{
@Override
public void browse() {
System.out.println("真实的服务器访问网络");
}
}
//代理类
class ProxyServer implements NetWork{
private NetWork work;
public ProxyServer(NetWork work){
this.work = work;
}
public void check(){
System.out.println("联网之前的检查工作");
}
@Override
public void browse() {
check();
work.browse();
}
}
7.内部类
Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类
1.成员内部类(静态、非静态):具备类的所有特性,同时也具备成员的可被4种不同的权限修饰
-
实例化成员内部类的对象
①静态的成员内部类:B.A a = new B.A();
②非静态的成员内部类:B b = new B(); B.A a = b.new A(); -
在成员内部类中区分调用内外部类的同名结构
②非静态的成员内部类:
this.属性方法 //调用内部类的
B.this.属性方法 //调用外部类的
2.局部内部类(方法内、代码块内、构造器内)