面向对象2

final

final可以修饰成员变量、局部变量、方法和类

final修饰的类不能被子类继承

final修饰的方法不能被子类重写

final修饰的基本数据类型变量,无法进行修改

final修饰的引用类型的变量,只保证地址不变,对象中的内容可以发生改变

补充:final可以和static联用,static和final的顺序可以颠倒,例static final int num = 2 表示静态成员常量一经赋值不可以改变,可通过类名.变量名来访问,注:这种方式不会加载类)

public class Test02 {	
	final static int num  = 2;	
	static {
		System.out.println("静态代码块");
	}	
	public static void main(String[] args) {	
		System.out.println(Test02.num);	
	}	
}
//下面是另一个测试类
public class Test03 {
	public static void main(String[] args) {	
		System.out.println(Test02.num);	
	}
}	

运行结果:
静态代码块
2
//下面的测试结果
2

第一种情况,因为main方法是静态的,所以会先去加载类,打印2条信息,第二种情况不会加载类只会打印2

//将常量值修改为随机数
final static int num  = (int)(Math.random()*30);	
运行结果:
静态代码块
28
//下面的测试结果
静态代码块
22

静态成员常量的值在加载前无法确定,那么会导致类加载。

math.random在加载前无所确定具体的值,故会先将Test02类加载

abstract

abstract关键字是和final对立的

abstract修饰类时,表示这个类是抽象类。

abstract修饰方法时,必须要被子类重写

abstract关键字不能修饰成员变量或局部变量

abstract不能和final一起修饰类

抽象类和接口

抽象类:

为什么需要抽象类?

避免子类的随意设计,提高了代码可读性 ,提高了子类的健壮性

1:抽象类中只能包含抽象方法吗?

否,抽象类既可以定义抽象方法也可以定义普通方法

2:是否可以定义构造器

抽象类可以存在构造器但是无法实例化

抽象类中的构造器是给子类准备的

抽象类就是用来被继承的 抽象方法就是被重写的

3:子类继承了抽象了之后一定要重写所有的抽象方法

接口的基本概念:

  • 接口是一个规范,是一套标准 ,比抽类更抽象,故不能实例化
  • 学习接口的方法和学习类是一样的
  • 接口定义的方式:修饰符 interface 接口名{}
  • 接口中的变量都是公开的,静态的最终常量值 ,默认情况下变量都是public static final修饰,调用时不会加载当前类
  • 接口中可以定义静态方法(不建议1.8)
  • 接口中定义的对象方法都是抽象方法 接口中的方法默认就是通过abstract修饰的
  • 接口中的默认方法从1.8之后才开始被使用 允许在接口中定义default方法 而且存在方法体

接口深入:

1、类和接口直接通过implements 发生关系 类实现接口

2、类必须要实现接口中的所有抽象方法,

3、一个类可以实现多个接口 类名 implements 接口1,接口2。。。。。

4、一个类实现了接口之后 要将当前接口以及接口的父接口中的所有抽象方法全部重写

5、接口可以多继承

6、接口无法实例化

7、接口没有构造器

8、接口中也可以使用多态

抽象类和接口经常被拿来进行比较,下面对它们进行了比较

抽象类接口
不可以实例化不可以实例化
用extends来继承用implements来实现
单继承、多实现可以多继承
抽象类里允许含有非抽象方法,抽象方法不能用private修饰接口的方法默认为public abstract型的,且只能为这个类型,(jdk8之后可以含有默认类型和静态方法)
可以有构造器不能有构造器
抽象类的所有抽象方法必须被子类重写,如果该子类也是抽象类不允许有同名的抽象方法,它的抽象方法最终要被一个不是抽象类的子类重写接口的所有方法必须被实现类实现即重写
class Son extends Father {
	void eat() {
		System.out.println("儿子吃饭");
	}	
}
abstract class Father extends Grandfather{		
}
abstract class Grandfather{
	 abstract void eat();
}

抽象类的抽象方法必须被最终子类(非抽象类)重写

类执行顺序

要理解类中的执行顺序,需要先了解代码块在类中的意义

代码块就是放在{}里的一段代码,可分为静态代码块、成员代码块 和局部代码块

静态代码块:

  • 声明在类中、方法外的代码块(有static关键字修饰)
  • 类加载的时候就会被加载并且只加载1次静态内容

成员代码块(也称初始化块):

  • 声明在类中、方法外的代码块 (没有static关键字修饰)
  • 初始化块在类加载的时候是不会执行的
  • 在创建对象之前会被调用(对于对象中的一些初始进行初始化操作)

局部代码块:

  • 声明在方法中的代码块
  • 缩减局部变量的生命周期,提高内存的使用率

类中的执行顺序:

  1. 首先执行静态内容(加载) 静态代码块
  2. 初始化块
  3. 构造器
public class Test04 {
	public static void main(String[] args) {
		new Son2().m();
	}
}

class Father{
	static {
		System.out.println("Father static");
	}
	{
		System.out.println("Father init");
	}
	public Father() {
		System.out.println("Father construct");
	}
}

class Son1 extends Father{
	static {
		System.out.println("Son1 static");
	}
	{
		System.out.println("Son1 init");
	}
	public Son1() {
		System.out.println("Son1 construct");
	}
}

class Son2 extends Father{
	static {
		System.out.println("Son2 static");
	}
	{
		System.out.println("Son2 init");
	}
	public Son2() {
		System.out.println("Son2 construct");
	}
	public void m() {
		new Son1();
	}
}
//运行结果:
Father static
Son2 static
Father init
Father construct
Son2 init
Son2 construct
Son1 static
Father init
Father construct
Son1 init
Son1 construct

当发生继承关系时,系统会先去加载父类,所以会先执行父类的静态代码块,然后再加载子类的静态代码块,执行完这步后子类要去调用构造器来创建对象,同样要先去调用父类的构造器,由于调用构造器是在创建对象,所以先执行初始代码块,再执行构造器,父类执行完后子类再执行,完成对象创建后,调用方法去创建另一个子类对象,同样先去加载父类的静态代码块,因为已经加载过一次所以不执行,后面重复前面的操作。

补充:(类加载的2种方式)

使用当前类中的静态方法、静态变量 (如果是调用final static修饰的静态成员常量不会进行类加载)

创建当前类的实例对象

类型转换(引用类型)

引用类型也有类型转换:

自动转换(向上转型):

父类型 变量名 = 子类对象;(new 子类对象|子类对象的变量)

强制转换(向下转型):

子类型 变量名 = (子类型)父类变量;

注:引用类型里面的类型转换和基本数据类型里的不同

要事先确定了父类变量中实际存储的对象是什么类型否则会报出

ClassCastException 类型转换异常

F f = new F();
S1 s1 = new S1(); 
s1.fun(); 
f = s1; 
//S2 s2 = (S2)f;编译错误
S1 ss = (S1)f; 

在这里f实际存储的是s1对象的地址,强转时必须转化为s1类型的,如果为其他类型,会报类型转换异常。

补充:null可以强转为任意类型 ,null也可以是任意类型(引用类型)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值