Java使用的扩展
1、JVM的内存模型
栈和堆的区别参考:https://blog.csdn.net/jianghao233/article/details/82777789
堆存放的是对象,
栈存放的是局部变量和对象的地址
2、单例设计模式
2.1、设计模式
设计模式是在软件工程实践过程中,程序员们总结出的良好的编程方法。使用设计模式能够增加系统的健壮性,易修改性和可扩展性,当你进行开发的软件规模比较大的时候,良好的设计模式会给编程带来便利,让系统更加稳定,
设计模式,即软件架构、实现思路,一方面便于后期扩展,二方面便于研发,各种框架如struts、ssh、spring mvc其实就是设计模式。
2.2、单例设计模式基本介绍
单例设计模式是在软件系统中采用一定的方法,保证某个类只能存在一个实例对象,并且该类只能有一个静态方法来获取该对象。比如如果实例化一个对象需要消耗大量的时间和资源的时候你可能就需要单例模式
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。
单例模式有以下特点:
- 单例类只能有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
示例代码:
import test.Singleton; public class Client { public static void main(String[] args){ Singleton singleton1 = Singleton.getInstance(); Singleton singleton2 = Singleton.getInstance(); System.out.println(singleton1 == singleton2); //true } }
2.3、饿汉式实现单例模式
该方式是静态常量实现的饿汉式(在类加载的时候就创建实例):
public class Singleton { //构造器私有化,防止new对象 private Singleton() {} //类内部实例化,赋值给私有的静态变量 private final static Singleton INSTANCE = new Singleton(); //对外提供公有方法调用 public static Singleton getInstance(){ return INSTANCE; } }
//使用单例设计模式的类 Singleton s = Singleton.getInstance();
饿汉式的单例模式的特点:
1)类加载的时候实例化,防止多线程问题。
2)没有使用懒加载,类加载就产生对象,如果始终未使用则造成内存浪费。但是该对象只有一个,浪费空间也不是很大,可以使用,编写的时候非常简单。
2.4、懒汉式实现单例模式
懒汉式实现单例模式,也就是在第一次调用方法的时候才创建实例。懒汉式和饿汉式的区别就在于在什么时候创建实例
public class Singleton { private static Singleton instance; //构造器私有化,防止new对象 private Singleton() {} //只有在第一次使用该方法的时候构造实例对象,使用synchronized避免多线程问题 public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
懒汉式的单例模式的特点:
1)解决了线程不安全问题
2)效率低下,每次调用该方法都要涉及锁的操作。
2.5、单例设计模式的使用场景
一个对象即可完成所有的工作,无需大量创建对象消耗资源。比如一个长连接,建立起来就可以不断发送数据,此时如果每来一个请求就建立一个连接,那么资源会消耗殆尽。一般来说,如果实例化一个类对象需要消耗过多资源或者是没必要多次创建实例对象时你就可以考虑使用单例设计模式。
3、Java中的初始化块
Java中初始化块(代码块)的作用是对 Java 对象进行初始化。
Java 中程序的执行顺序:1、声明成员变量的默认值 2、成员变量在声明时显式赋值 3、多个代码块依次被执行 4、类的构造函数对成员进行赋值
Demo04 d = new Demo04(); //下面标出在执行实例化时程序的执行顺序 public class Demo04 { public int num = 0; //1 public Demo04() { //4 this.num = 10; } { //2 System.out.println("执行代码块"); } { //3 System.out.println("执行代码块"); } }
3.1、静态代码块
一个类中初始化块如果有修饰符,则只能被 static 修饰,称为静态代码块。
静态代码块随着类的加载而执行,而且只执行一次。静态代码块在多次创建实例对象时只会执行一次,非静态代码块在每次实例化时都会被执行。静态代码块的执行优先级高于非静态的初始化块,它会在类初始化的时候执行一次,执行完成便销毁。
如果有些代码必须在项目启动的时候就执行,需要使用静态代码块。我们一般使用静态代码块来初始化比较复杂的类变量,即 static 修饰的数据成员。
实例代码如下:
public class UtilTest { private static String val; static { UtilTest.val = "初始化值"; } }
4、Java中的工厂模式
工厂模式就是用工厂方法(返回一个实例化对象)来生成类的实例对象,代替 new 的操作,需要 new 一个对象的时候就直接调用工厂方法。
工厂模式可以避免一旦类发生了一些改变(比如类名改变)时,项目中所有对该类的实例化都需要修改的情况,使用了工厂模式后,类发生修改只需要修改相应的工厂方法即可。
class Mouse{ public void sayHi(){}; } class DellMouse extends Mouse{ @Override public void sayHi() { System.out.println("产品:戴尔鼠标"); } } class HpMouse extends Mouse{ @Override public void sayHi() { System.out.println("产品:惠普鼠标"); } }
//生产工厂接口 interface MouseFactory{ public Mouse createMouse(); } //不同的鼠标交由不同的工厂生产 //惠普鼠标工厂方法 class HpMouseFactory implements MouseFactory{ @Override public Mouse createMouse() { return new HpMouse(); } } //戴尔鼠标工厂方法 class DellMouseFactory implements MouseFactory{ @Override public Mouse createMouse() { return new DellMouse(); } } //测试类 public class Test { public static void main(String[] args) { MouseFactory hpFact = new HpMouseFactory(); MouseFactory dellFact = new DellMouseFactory(); Mouse hpm = hpFact.createMouse(); Mouse dellm = dellFact.createMouse(); hpm.sayHi(); dellm.sayHi(); } }
5、内部类
可以将一个类的定义放在里另一个类的内部,这就是内部类,内部类可以有多个。
//外部类(外部是相对内部而言) public class Outer{ public String name; //内部类 class Inner{ Outer.this.name = "wen"; //访问外部类属性 ... } }
- 内部类可以声明为 final
- 和外部类不同,内部类可以声明为 private 或者 protected。
- 内部类可以声明为 static,但此时就不可以使用外部类的非 static 成员变量
- 内部类可以声明为抽象类,被其他内部类继承
5.1、内部类的作用
使用内部类可以间接地解决 Java 中类无法多继承的问题。
内部类拥有类的基本特征,它可以继承父类,实现接口,无论外部类是否已经继承了某个类或者实现了某个接口,对于内部类都没有影响。我们可以通过内部类来继承其他的类,由此外部类就可以通过内部类来访问多个其他类的方法或者属性,间接实现了多重继承。
//下面 A 类间接继承了 B和C 类,拥有了 B和C 的方法 class A { //方法中调用内部类方法 public void TestB () { new InnerB().testB(); } public void TestC () { new InnerC().testC(); } //通过内部类继承B private class InnerB extends B { @Override public void TestB() { ... } } //通过内部类继承C private class InnerC extends C { @Override public void TestB() { ... } } } class B { public void testB(){} } class C { public void testC(){} }