【Java 08】面对对象(下) - static、单例设计模式、代码块、final

25 篇文章 0 订阅
20 篇文章 0 订阅

一 面向对象上一

1 对三大特性的理解

1.1 封装性

指一个类把自己内部的实现细节进行隐藏,只暴露对外的接口(setter和getter方法)。

封装又分为属性的封装和方法的封装。把属性定义为私有的,它们通过setter和getter方法来对属性的值进行设定和获取。

总体上体现为四种权限修饰

1.2 继承性

指在一个现有类(父类)的基础上在构建一个新类(子类),子类可以拥有父类的成员变量以及成员方法(但是不一定能访问或调用,例如父类中private私有的成员变量以及方法不能访问和调用)。

继承的作用就是能提高代码的复用性。子类拥有父类中的一切(拥有不一定能使用),它可以访问和使用父类中的非私有成员变量,以及重写父类中的非私有成员方法。

继承的好处是实现代码的复用以及扩展,子类通过对父类代码的复用,可以不用再定义父类中已经定义的成员变量,方法上直接对父类的方法进行重写实现了扩展。

1.3 多态性

多态就是指多种状态,就是说当一个操作在不同的对象时,会产生不同的结果。(给对象一个激励,让对象自行决定应该做出何种响应。)

在Java中,实现多态的方式有两种,一种是编译时的多态,另外一种是运行时多态,编译时的多态是通过方法的重载实现的,而运行时多态是通过方法的重写实现的。

方法的重载是指在同一个类中,有多个方法名相同的方法,但是这些方法有着不同的参数列表,在编译期我们就可以确定到底调用哪个方法。

方法的重写,子类重写父类中的方法(包括接口的实现),父类的引用不仅可以指向父类的对象,而且还可以指向子类的对象。当父类的引用指向子类的引用时,只有在运行时才能确定调用哪个方法。

其实在运行时的多态的实现,需要满足三个条件:1.继承(包括接口的实现)2.方法的重写 3.父类的引用指向子类对象

并且,我们说的多态都是类中方法的多态,属性是没有多态性的。

  1. 实现代码的通用性

  2. Object类中定义的public boolean equals(Object obj){}

    JDBC:使用java程序操作(获取数据库连接、CRUD)数据库

  3. 抽象类、接口的使用肯定体现了多态性(抽象类、接口不能实例化)

  4. 多态是运行时行为,取随机数证明,编译时看不出,运行时才看得出

2 static关键字

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kPZ9zh8Z-1597115758298)(C:\Users\吴淼杰\Desktop\笔记\Java\Java08 面向对象上一\image-20200810053314898.png)]

static:静态的

static可以用来修饰:属性、方法、代码块、内部类

2.1 使用static修饰属性:静态变量

属性按是否使用static修饰,又分为:静态变量(类变量) VS 非静态属性(实例变量)

实例变量:当创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。当修改其中一个对象中的非静态属性时,不会对其他对象同样的属性值产生改变

静态变量:当创建了类的多个对象,多个对象共享同一个静态变量。当通过一个对象修改静态变量时,会导致其他对象调用此静态变量时,是被修改过的。

2.1.1 其他说明
  1. 静态变量随着类的加载而加载,可以通过**“类名.静态变量”/“对象名.静态变量”**的方式进行调用

  2. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RZvwFiuI-1597115758307)(C:\Users\吴淼杰\Desktop\笔记\Java\Java08 面向对象上一\image-20200810142803203.png)]

  3. 静态变量的加载早于对象的创建

  4. 由于类只会加载一次,则静态变量在内存中也只会存在一份,存在方法区的静态域中

2.1.2 举例

System.out

Math.PI

2.1.3 内存结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-taZYj6n0-1597115758310)(C:\Users\吴淼杰\Desktop\笔记\Java\Java08 面向对象上一\image-20200810142454820.png)]

2.2 使用static修饰方法:静态方法

2.2.1 说明
  1. 静态方法随着类的加载而加载,可以通过**“类名.静态方法”/“对象名.静态方法”**的方式进行调用

  2. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-izO4hiHb-1597115758314)(C:\Users\吴淼杰\Desktop\笔记\Java\Java08 面向对象上一\image-20200810142917695.png)]

  3. 静态方法中,只能调用静态的属性或方法

    非静态方法中,既可以调用非静态的属性或方法,也可以调用静态的属性或方法

    从生命周期考虑

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XGorPPbD-1597115758317)(C:\Users\吴淼杰\Desktop\笔记\Java\Java08 面向对象上一\image-20200810143343374.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8zlTs5Az-1597115758320)(C:\Users\吴淼杰\Desktop\笔记\Java\Java08 面向对象上一\image-20200810143707462.png)]

2.3 static注意点

  1. 在静态的方法中,不能使用this关键字,super关键字
  2. 关于静态属性和静态方法的使用,从生命周期的角度去理解

2.4 总结

2.4.1 在开发中,如何确定一个属性是否要声明为static?
  • 属性是可以被多个对象共享的,不会随着对象的不同而不同的
2.4.2 在开发中,如何确定一个方法是否要声明为static?
  • 操作静态属性的方法,通常设置为static的
  • 工具类中的方法,习惯上声明为static的。比如:Math、Arrays、Collections…

2.5 代码实例

public class CircleTest{
    public static void main(Stinr[] args){
        
        Circle c1 = new Circle();
        Circle c2 = new Circle();
        System.out.println(c1.getId());//1001
        System.out.println(c2.getId());//1002
        System.out.println(Circle.getTotal());//2
        
    }
}

class Circle{

	private double radius;
    private int id;
    
    public Circle(){
        id = init++;
        total++;
    }
    
    public Circle(double radius){
        this();
        this.radius = radius;
        //id = init++;
        //total++;
    }
    
    private static int total;
    private static int init = 1001;//属性被所有对象共享
    
    public double findArea(){
        return 3.14 * radius * radius;
    }
    
    //get和set方法

}

3 单例(Singleton)设计模式

  • 设计模式**是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。**设计模式免去外面总结再思考和摸索。式就像是经典的棋谱,不同的器具,外面用不同的棋谱,“套路”
  • 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。如果外面要让类在一个虚拟机中只能产生一个对象,我们首先必须将类的构造器的访问权限设置为private,这样,就不能有new操作符再类的外部产生类的对象了,但是在类的内部可以产该类的对象。因为在类的外部开始还无法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对称,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的

3.1 代码实现

3.1.1 饿汉式
public class SingletonTest1{

    Bank bank1 = Bank.getInstance();
    Bank bank2 = Bank.getInstance();
    bank1 = bank2;//true
        
}

class Bank{

	//1.私有化类的构造器
    private Bank(){
        
    }

    //2.内部创建类的对象
    //4.要求此对象也必须声明为静态的
    private static Bank instance = new Bank();
    
    //3.提供公共的静态的方法,返回类的对象
    public static Bank getInstance(){
        return instance;
    }
    
}
3.1.2 懒汉式
public class SingletonTest1{

    Bank bank1 = Bank.getInstance();
    Bank bank2 = Bank.getInstance();
    bank1 = bank2;//true
        
}

class Bank{

	//1.私有化类的构造器
    private Bank(){
        
    }

    //2.声明当前类对象,没有初始化
    //4.要求此对象也必须声明为静态的
    private static Bank instance = null;
    
    //3.提供公共的静态的方法,返回类的对象
    public static Bank getInstance(){
        if(instance == null){
            instance = new Bank();
        }
        return instance;
    }
    
}
3.1.3 两者优缺点
  1. 饿汉式
    • 坏处:对象加载时间过长
    • 好处:线程安全
  2. 懒汉式
    • 好处:延迟对象的创建
    • 坏处:线程不安全

3.2 举例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G9tOuW65-1597115758322)(C:\Users\吴淼杰\Desktop\笔记\Java\Java08 面向对象上一\image-20200810171108232.png)]

3.3 应用情景

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eAEihtNM-1597115758323)(C:\Users\吴淼杰\Desktop\笔记\Java\Java08 面向对象上一\image-20200810171200345.png)]

4 理解main方法的语句

public class MainTest{
    public static void main(String[] args){
        
    }
}

main也可以通过控制台传入数据,运行时传入 (String[] args)

5 类的成员之四:代码块(Block)

开发中好鸡肋的东西…

public class BlockTest{
    public static void main(String[] args){
        
        String desc = Person.desc;//Hi,static block
        
        Person p1 = new Person();//Hi,block
        Person p2 = new Person();//Hi,block
        
    }
}

public class Person{
	
    //属性
    String name;
	int age;
    static String desc = "我是一个人";
	
    //构造器
	public Person(){
	
	}
	
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
    
    //代码块
    //静态代码块
    static{
        System.out.println("Hi,static block1");
    }
    static{
        System.out.println("Hi,static block2");
    }
    
    //非静态代码块
    {
        System.out.println("Hi,block");
    }
	
    //方法
	public void eat(){
	
	}
	
	public void sleep(){
	
	}
    
    //toString重写
    public String toSting(){
        
    }
}

5.1 作用

用来初始化类、对象

5.2 注意

代码块如果有修饰,只能使用static

5.3 分类

开发中没有必要造多个代码块

5.3.1 静态代码块
  1. 内部可以有输出语句
  2. 随着类的加载而执行,而且只执行一次
  3. 作用:初始化类的属性等
  4. 如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
  5. 静态代码块的执行优先非静态代码块的执行
5.3.2 非静态代码块
  1. 内部可以有输出语句
  2. 随着对象的创建而执行
  3. 每创建一个对象,就执行一次
  4. 作用:初始化对象的属性等
  5. 如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行

5.4 继承情况初始化顺序实例

class Parent {
	/* 静态变量 */
	public static String p_StaticField = "父类--静态变量";
    
	/* 变量 */
	public String p_Field = "父类--变量";
	protected int i = 9;
	protected int j = 0;
    
	/* 静态初始化块 */
	static {
		System.out.println( p_StaticField );
		System.out.println( "父类--静态初始化块" );
	}
    
	/* 初始化块 */
	{
		System.out.println( p_Field );
		System.out.println( "父类--初始化块" );
	}
    
	/* 构造器 */
	public Parent()
	{
		System.out.println( "父类--构造器" );
		System.out.println( "i=" + i + ", j=" + j );
		j = 20;
	}
}

public class SubClass extends Parent {
	
    /* 静态变量 */
	public static String s_StaticField = "子类--静态变量";
    
	/* 变量 */
	public String s_Field = "子类--变量";
    
	/* 静态初始化块 */
	static {
		System.out.println( s_StaticField );
		System.out.println( "子类--静态初始化块" );
	}
    
	/* 初始化块 */
	{
		System.out.println( s_Field );
		System.out.println( "子类--初始化块" );
	}
    
	/* 构造器 */
	public SubClass()
	{
		System.out.println( "子类--构造器" );
		System.out.println( "i=" + i + ",j=" + j );
	}


	/* 程序入口 */
	public static void main( String[] args )
	{
		System.out.println( "子类main方法" );
		new SubClass();
	}
}

初始化顺序

父类–静态变量/父类–静态初始化块
子类–静态变量/子类–静态初始化块 + 子类main方法
父类–变量/父类–初始化块
父类–构造器
子类–变量/子类–初始化块
子类–构造器

总结由父及子,静态先行

5.5 初始化顺序

  1. 默认初始化 -->

  2. 显式初始化 / 代码块初始化 (关注谁先写谁后写) -->

  3. 构造器初始化 -->

  4. 有了对象后,通过“对象.属性” “对象.方法”进行赋值

6 final关键字

final:最最终的

final可以用来修饰:类、方法、变量

6.1 使用final修饰类

final class FinalA{
    
}

final用来修饰一个:此类不能被继承,无子类(太监类)

比如:String类、System类、StringBuffer类

6.2 使用final修饰方法

final用来修饰一个方法:此方法不能被重写

比如:Object类中的getClass()

6.3 使用final修饰变量

final用来修饰一个变量:此时的“变量”就称为一个常量

6.3.1 final修饰属性

可以考虑赋值的位置有:显式初始化、代码块初始化、构造器初始化

6.3.2 final修饰局部变量
public void show(){
	final int NUM = 10;
}

public void show(final int NUM){
	system.out.println(NUM);
}

尤其是final修饰形参时,表明此形参是一个常量

当我们调用此方法时,给常量形参赋一个实参。

一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值

6.4 static final

修饰属性、方法

6.4.1 修饰属性

static final 全局常量(表示属性不能改变)

修饰方法少见

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值