继承和final和单例

什么是继承
面向对象的三特性:封装、继承、多态
面向对象特征:继承

把多个类公共的部分提取出来,作为一个父类。

用继承的好处

  1. 优化设计
  2. 方便修改代码
  3. 减少代码量

(重复代码可以不用写,直接放在父类中,到时候子类去调就行)

特点

  • 子类与父类is - a关系。(子类 is a 父类)
  • 其他类用extends关键字可以继承父类
  • 可以继承所有的属性和方法
    (私有的属性和方法不可见,不代表没有继承)
  • 被继承的方法就是自己的 不需要造父类对象
  • 子类不能调用父类私有方法 ,只能继承可见的 ,虽然实际上都继承了。
  • 私有的属性也不可见,但也继承了,要用需要使用getter。
    (私有化的目的不让访问)

子类继承父类的什么?
继承public和protected修饰的属性和方法,不管子类和父类是否在同一个包里
继承默认权限修饰符修饰的属性和方法,但子类和父类必须在同一个包里

如何使用继承?
父类

[访问修饰符] class Pet { 
    //公共的属性和方法
}

子类(继承父类)

[访问修饰符] class Dog extends Pet { //继承关键字
    //子类特有的属性和方法
}

继承是Java中实现代码重用的重要手段之一。
Java中只支持单(根)继承,即一个类只能有一个直接父类。

不能继承父类构造方法,但默认会调用父类构造。
这是Java里的规范。(也可以用super()来调用)
但也有一种说法所有子类默认的构造方法是从父类传递来的,
最终是Object。

理解继承

子类访问父类成员

  1. 访问父类构造方法
    super(); //父类无参构造
    super(name);//父类有参构造

  2. 访问父类属性
    super.name;

  3. 访问父类方法
    super.print();

super关键字来访问父类的成员

  1. 使用super关键字,super代表父类对象

(1) this 代表本类对象
(2)在没有(同名属性、同名方法)冲突的情况下,this和super效果相同。
(3)this和super只有重名才有实际意义
(4)子类和父类都有同名属性,那么子类就会覆盖从父类继承的属性。
(5)正常情况,子类里用的是this ,除非你专门用super 来赋值
但父类对象拿不到 也没有意义
(6)父类的有参方法,子类不能直接调用,必须在子类用super才能调用

  1. 在子类构造方法中调用且必须是第一句
  2. 不可以访问父类中定义为private的属性和方法
  3. super只能出现在子类的方法和构造方法中

继承条件下的构造方法

public class Father {
	public Father() {
		System.out.println("爸爸在这里!");
	}
}
public class Son extends Father{
	public Son() {		
		System.out.println("儿子在这里!");
	}
	public static void main(String[] args) {
		Son s1 = new Son();
		//内存当中,先创建父类对象,再创建子类对象
	}
}

结果为
爸爸在这里!
儿子在这里!

  1. 继承的时候,创建子类对象必须先隐式创建父类对象

  2. 只要父类有无参构造,创建子类时,会先执行父类无参。

父类没写构造方法,那就默认有个无参构造,子类都能执行。
(隐性创建,没有办法显式的去调用它)

子类构造不指定哪个父类构造器,那就是默认调用父类无参构造器。

  1. 父类如果有有参构造,最好不去掉无参构造。

子类有有参构造时(父类有有参构造和无参),执行的还是父类无参构造。
必须要有父类无参构造,不然子类就会报错。(没有父类哪来的子类)

  1. 如果父类只有有参构造,这时没有无参构造,
    子类的构造方法会失效,除非子类用super显式调用父类有参构造。
    (super(类型对应的值))

子类构造方法通过super显式调用父类的有参构造方法
(此时父类无参构造方法不会执行)
执行父类相应构造方法,而不执行父类无参构造方法

  1. 子类构造方法能通过this显式调用自身的其他构造方法。

  2. 子类的构造方法是建立在父类的构造方法上的。
    当父类只有有参,子类啥也没有来造个对象,就会报错
    父类必须要有无参,子类才能创建对象

  3. 不能同时调父类的有参和无参 ,只能选择一种方式生成。

注意点

所有的构造方法都是来自于Object类 (隐式的可以不写)
Object类是所有类型的父类

子类可以继承父类的所有资源吗?
不能被使用的父类成员

  1. private成员
  2. 子类与父类不在同包, 使用默认访问权限的成员
  3. 构造方法

何时使用继承?

  • 符合is-a关系的设计使用继承
  • 继承是代码重用的一种方式
    将子类共有的属性和行为放到父类中

单例模式
要求某一个类只有一个对象。
(设计模式中的最简单的一种)

好处是 :(摘录)

  1. 实现了整个程序对唯一实例访问的控制。
  2. 因为单例要求程序只能有一个对象,
    所以对于那些需要频繁创建和销毁的对象来说可以提高系统的性能,
    并且可以节省内存空间。
  3. 可以全局访问。
  4. 允许可变数目的实例。

坏处是:(摘录)

  1. 不适用于变化频繁的对象。
  2. 符合的场景有限。
  3. 如果实例化的对象长时间不被利用,
    系统会认为该对象是垃圾而被回收,可能会导致对象状态的丢失
  4. 可扩展性较差。

懒汉式:(更推荐)(拿时间换空间)
第一次调用这个方法的时候对象才会被创建。
(通俗地讲,只有我要你,你才会创建,节约内存空间)

好处:延迟对象的创建

public class Singleton {
	private static Singleton s;//本类的静态对象(变量)
	private Singleton() {}
	//构造器私有化,不让外界随便造对象
	//造一个static方法,通过类名.方法来在外界造对象
	//在静态方法中,不能引用成员变量(即,没有static修饰的变量)。
	//可以引用类变量(即,static修饰的变量)。
	public synchronized static Singleton getInstance() {
		if(s == null) {
			s = new Singleton();
		}
		return s;
	}
}

synchronized:同步锁 (保证线程安全)
在同一时间,只能有一个线程进入到里面,不然就会引起并发问题。

饿汉式:(拿空间换时间)
只要访问这个类型,第一时间会先创建对象,哪怕你没有调用任何东西,
下次调用的时候,你就不需要在判断,节省了运行时间。
坏处:对象加载时间过长
如果内容过多,全部调用,可能会浪费空间。
好处:饿汉式是线程安全的

public class Singleton2 {
	private static Singleton2 s;
	static {
		s = new Singleton2();
	}
	public static Singleton2 getInstance() {
		return s;
	}
	//返回出去
}

注意点

不管创建多少个对象(外界),它们的地址都是一样。都是s这个对象,没区别。

只要这个地址被创建出来,你在外界无论用什么方法都没有办法改变它的地址。(除了本类)

题外话
final 关键字

  • 只要加上final (final修饰的类)就不能被继承!!!
    举例:string类就是final类
  • final修饰的方法是不能被子类重写 但可以用反射!
  • final修饰(成员)变量就是常量,不可被修改,不能再被赋值。

常量是指不能被修改的值,不是指数字

public static final共同修饰成员变量来表示常量,
常量的命名规则是:所有字母都大写,不同单词之间使用下划线连接。
如: public static final double PI = 3.14;

为什么static final 一般放一起使用呢?

static修饰属性的时候是静态的。 (从属于类)
即静态成员变量在类加载的时候就进行了创建,在整个程序时按序销毁。
当一个静态常量需要我们反复使用的时候,我们就需要使用这种方法。

初始化顺序

public class People {
	static {
		System.out.println("我是people静态方法");
	}
	public People() {
		System.out.println("我是people构造方法");
	}
}
public class Student extends People{
	static {
		System.out.println("我是stu静态方法");
	}
	public Student() {
		System.out.println("我是stu构造方法");
	}
}
public class Test {
	public static void main(String[] args) {
		Student student = new Student();
	} 
}

结果
我是people静态方法
我是stu静态方法
我是people构造方法
我是stu构造方法

类加载的时候(Studnet student), 先执行static代码块,先父类再子类,
再创建对象的时候 (new studnet ) ,然后执行构造方法,先父类再子类。

类的初始化过程

  1. 加载class文件
  2. 堆中开辟空间
  3. 变量的默认初始化
  4. 变量的显示初始化
  5. 构造代码块初始化
  6. 构造方法初始化

开源 可以看源代码

工作时,class 文件给别人,Java文件是源文件,不方便被别人看到。
jvm 看的是class文件,只读字节码。

要打印的话,就不能用return,用void类型方法

----2021.08.07

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值