day7-面向对象进阶
-
String与StringBuffer,StringBuilder
-
static关键字
-
设计模式之单例模式
-
JDK1.7新增Objects类
-
final关键字
-
抽象类
-
设计模式之模板方法
String与StringBuffer,StringBuilder
String在java中表示定长字符串,一旦对String初始化,则无法修改内容,除非重新赋值(创建新对象),所以String在进行大量字符串拼接时会频繁创建新对象,从而影响程序的运行效率;
StringBuffer是一个长度可变的字符序列,可以动态在原来字符串缓冲区的基础上追加(append)或者插入(insert)新的字符序列,而不会修改对象的内存地址,所以使用StringBuffer在完成字符串拼接时效率较高,另外StringBuffer是线程安全的实现,所以在线程并发操作时效率会有所影响
StringBuilder跟StringBuilder具备相同的API(构造器,方法等),但是StringBuilder是不执行同步(线程不安全),因此效率会高于StringBuffer.
static关键字
static可以用于修饰内部类,属性,方法,游离块;被static修饰的元素与实例无关(与对象无关),与类直接相关,一旦类被加载则static修饰的元素都会被初始化,static修饰的元素有最高存活优先级,即便普通引用对象被GC回收时,static修饰相关资源不会立即回收;被static修饰的属性,方法,内部类称之为静态属性,静态方法,静态内部类,这些元素都无需创建对象调用,可以直接通过类名(加".")进行调用,一般static用于常量定义,一些工具类中的方法,需要反复执行,但是不需要反复创建。
-
实例变量,实例方法(需要通过对象进行调用,属于对象的)
-
类变量,类方法(直接与类相关的静态元素)
关于static元素的注意事项
不允许在静态方法中使用非静态元素(静态方法被调用时可能对象还未创建,非静态元素都需要通过对象调用)
静态元素只会在类加载时初始化一次
static语句块
通过在游离快前加上static关键,以表示当前语句块是一个静态游离快,静态游离快一旦类被加载之后,static语句块会立即执行,并且只会执行一次,不会因为对象的多次创建而执行多次。
public class Block{
static{
//...执行一些程序运行时不需要反复执行的代码,比如连接数据库时的驱动加载,常用资源的获取
}
}
设计模式之单例模式
设计模式,一些用于解决某些特定需求的通用设计方法,java中常用设计模式包含23种;
单例模式(Singleton),在程序的运行期间某个对象的实例始终只会存在一个,不存多少次获取,获得的始终是同一个实例对象,单例模式的设计原则:
-
构造器必须私有化,防止外界随意访问
-
提供static方法用于获取对象实例
单例模式的实现方式包含三种:
-
饱汉模式
-
饿汉模式
-
双重锁模式
饱汉模式(延迟创建)
public class Singleton{
private static Singleton instance;
private Singleton(){}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
饿汉模式(饥渴创建)
public class Singleton{
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
final关键字
final可以用于修饰类,方法,属性,被final修饰的元素:
-
final修饰的类不可被继承(断子绝孙类)
-
final修饰的变量不可被改变(常用于与static组合进行常量的声明)
-
final修饰的方法是不允许被重写
final、finally,finalize区别?
Objects类
jdk1.7之后新增一个对Object对象进行空指针安全操作的相关工具类,里面提供了一些列空指针安全的方法
String s1 = null;
String s2 = new String("hello");
// if(s1 != null){
// System.out.println(s1.equals(s2));
// }
System.out.println(Objects.equals(s1, s2));
System.out.println(Objects.deepEquals(s1, s2));
//基于空指针安全的hashcode获取
System.out.println(Objects.hashCode(s1));
//基于空指针安全的对象是否为空判断
System.out.println(Objects.isNull(s1));
//基于空指针安全的对象是否不为空判断
System.out.println(Objects.nonNull(s2));
//基于空指针安全的对象toString操作
System.out.println(Objects.toString(s1));
抽象类(abstract)
抽象类是java中的重要特点之一,当一个类中包含的一些信息不足以描述一个对象时该类可以定义为抽象类,可以将一个类,方法使用abstract关键字修饰,使用abstract修饰的类无法被实例化,使用abstract修饰的方法不能有具体的实现,必须由子类实现
abstract class 类名称{
//已实现方法 //未实现方法(abstract method)
}
public abstract class Animal {
private String name;
//抽象方法
public abstract void sleep();
public void setName(String name){
this.name = name;
}
}
关于抽象类
抽象类中不一定包含抽象方法,包含抽象方法的类一定是抽象类
抽象方法不能有实现体,只包含方法定义
子类对抽象类继承了则子类必须实现抽象类中的抽象方法
抽象类也可继承抽象类(只能继承一个直接抽象类)
抽象类包含构造器,但是无法实例化
设计模式之模板方法模式
在类中定义了某个算法的骨架,但不具体实现,而在其子类中实现,例如,银行计算利息,都是利率乘以本金和存款时间,但各种存款方式计算利率的方式不同,所以,在账户这个类的相关方法里,只搭出算法的骨架,但不具体实现。具体实现由各个子类来完成;以上定义算法骨架由子类实现的设计模式称之为模板方法模式。
/**
* 账户类
* @author mrchai
*/
public abstract class Account {
private double interest; //利息
private double fund; //本金
public Account(double fund) {
this.fund = fund;
}
/**
* 获取利息
* @return
*/
public double getInterest(){
return fund * getInterestRate();
}
/**
* 由于不同存款类型和时间决定不同的利率,所以利率的获取无法直接确定
* @return
*/
public abstract double getInterestRate();
}
子类A:
/**
* 定期账户
* @author mrchai
*/
public class AccountTypeA extends Account{
private int year; //存款年限
private double base = 0.01; //基本利率
public AccountTypeA(double fund,int year) {
super(fund);
this.year = year;
}
@Override
public double getInterestRate() {
return year * base;
}
}
子类B:
/**
* 活期账户
* @author mrchai
*
*/
public class AccountTypeB extends Account {
private double base = 0.005;//基本利率
public AccountTypeB(double fund) {
super(fund);
}
@Override
public double getInterestRate() {
return base;
}
}
测试类:
public class AccountTest {
public static void main(String[] args) {
//定义本金
double fund = 1000000;
//创建A型账户
AccountTypeA a = new AccountTypeA(fund,5);
System.out.println(a.getInterest());
//创建B型账户
AccountTypeB b = new AccountTypeB(fund);
System.out.println(b.getInterest());
}
}