Java_面向对象(下)

本文深入讲解Java中的关键概念,如代码块、继承、方法重写、多态等,并详细阐述了抽象类、接口以及类之间的关系等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内容概述

  • 代码块
  • 继承
  • 方法重写
  • final关键字
  • 多态
  • 抽象类
  • 接口
  • 多态的形式
  • 类与类、类与接口、接口与接口的关系
  • 抽象类和接口的区别
  • 类名、抽象类、接口作为形参和返回值
  • 访问修饰符
  • 内部类

代码块

1.代码块的分类:
1).局部代码块
在某个方法中,或者某个代码块中;
执行:顺序执行;
作用:限制变量的声明周期;
public class Demo {
	public static void main(String[] args){
		{
			int n = 10;//如果这个非常占用内存
			System.out.println("n = " + n);//模拟使用变量
		}
		//代码到这里,就释放了n的内存;
	}
}
2).构造代码块:
定义在"类体中";
执行:每次实例化这个类的对象时,都会被执行一次;
作用:一般也是用于类的初始化操作,跟"构造方法"的作用一样,区别:构造代码块不能带参数;
注意:如果跟构造方法同时存在,先执行"构造代码块";
3).静态代码块:
定义在"类体中";使用static修饰的一个代码块;
执行:第一次使用这个类时,会被执行一次;之后就不再被执行;
作用:用于初始化"静态成员";它可以访问成员变量,但仍然只能访问静态成员变量;
注意:执行顺序:静态代码块-->构造代码块-->构造方法
作用:初始化成员变量。
执行流程:
1.普通构造代码块:每次实例化此类对象时,会被执行。它会先于"构造方法"被执行;
2.静态代码块:第一次实例化此类对象时;
3.静态代码块-->普通构造代码块-->构造方法:
eg:
class Fu {
	static {
		System.out.println("静态代码块Fu");
	}

	{
		System.out.println("构造代码块Fu");
	}

	public Fu() {
		System.out.println("构造方法Fu");
	}
}
class Zi extends Fu {
	static {
		System.out.println("静态代码块Zi");
	}

	{
		System.out.println("构造代码块Zi");
	}

	public Zi() {
		System.out.println("构造方法Zi");
	}
}
public class Demo {
	public static void main(String[] args){
		Zi z = new Zi();
	}
}
输出结果为:
静态代码块Fu
静态代码块Zi
构造代码块Fu
构造方法Fu
构造代码块Zi
构造方法Zi

继承

1.使用关键字:extends
2.作用:代码重用。为多态提供了前提;
3.this和super的区别:
a.this:
1).每个类都有的一个隐式的变量;
2).存储是当前对象的引用,是实例化此类的对象时,由JVM自动为其赋值的;
3).this可以访问本类的成员变量、成员方法、构造方法;
4).使用this()调用本类其它构造方法的注意事项:
A.this()调用其它构造方法,这种语句只能出现在某个构造方法中;
B.如果调用带参的构造方法,可以使用this(实参)方式调用;
C.构造方法不能"递归调用";
D.this()调用其它构造方法时,这种语句必须出现在这个构造方法的第一行有效语句;
5).什么时候必须使用this:
A.局部变量覆盖成员变量;使用this访问被覆盖的成员变量;
B.在本类的一个构造方法中调用本类的另一个构造方法时。this()或this(实参)
b.super:
1).每个类都有的一个隐式的变量;
2).存储的是父类对象的引用;是实例化子类对象时,由JVM自动为其赋值的;
3).super可以访问父类的成员变量、成员方法、构造方法;
4).使用super()调用父类的构造方法的注意事项:
A.super()调用父类构造方法的语句,只能出现在子类的某个构造方法内;
B.使用super(实参)可以调用父类带参数的构造方法;
C.super()调用父类的构造方法时,这条语句必须出现在子类构造方法的第一条有效语句;
5).什么时候必须使用super:
A.子类成员覆盖了父类成员时,可以使用(super.父类成员)访问父类的被覆盖的成员;
B.如果父类中没有无参构造方法,子类的每个构造方法都必须的使用super(实参)调用父类中带参的构造方法;
注意:在一个构造方法中,不能同时使用this()和super()。因为它们都需要在第一行有效语句;
4.类的初始化过程:
加载class文件
堆中开辟空间
变量的默认初始化
变量的显示初始化
构造代码块初始化
构造方法初始化
 成员变量-->构造代码块-->构造方法
5.Java中继承的特点:
1).Java中只能单继承;
2).Java中可以多级继承;
6.继承的好处和弊端:
好处:
1).代码复用
2).提高了代码的可维护性;
3).为多态提供了前提;
弊端:
1).由于继承,子类对父类产生了依赖;
7.继承的注意事项:
1).子类只能继承父类所有非私有的成员(成员方法和成员变量)
其实这也体现了继承的另一个弊端:打破了封装性
2).子类不能继承父类的构造方法,但是可以通过super(后面讲)关键字去访问父类构造方法。
3).不要为了部分功能而去继承;
8.什么时候使用继承:
继承中"类"之间体现的是:"is a(是一个)"的关系。
9. 继承中构造方法的关系:
1).当我们实例化一个子类对象时,JVM会自动调用父类"无参的"构造方法,实例化一个父类对象;
2).如果父类没有无参构造方法,那么子类的任何的构造方法中,都必须的显示使用super(实参)调用父类中带参的构造方法;
eg:
/*
	铺垫的小知识:
	第一个:成员变量有基本类型和引用类型的。
	class Demo {
		//基本类型
		int x = 10;
		//引用类型
		Student s = new Student();
	}
	第二个:类的初始化过程
		加载class文件
		堆中开辟空间
		变量的默认初始化
		变量的显示初始化
		构造代码块初始化
		构造方法初始化
	第三个:遇到extends,就要知道,先初始化父类数据,然后初始化子类数据。
		分层初始化。
		super在这里仅仅表示要先初始化父类数据。
*/
class X {
	Y b = new Y();
	X() {
		System.out.print("X");
	}
}
class Y {
	Y() {
		System.out.print("Y");
	}
}
class Z extends X {
	Y y = new Y();
	Z() {
		System.out.print("Z");
	}
}
class Demo3 
{
	public static void main(String[] args) 
	{
		new Z();//YXYZ
	}
}

方法重写

1.在子类中,定义跟父类一模一样的方法,这叫:方法重写;
2.重写的规则:
1).返回值类型、方法名、形参列表:要完全一致;
2).子类的访问修饰符可以跟父类的相同,或更宽;
3.重写的意义:
1).子类保留了父类的方法,具有了自己特有的行为;
4.重写和重载的区别:
1).重写:在子类中定义跟父类一模一样的方法;
2).重载:在一个类中,定义:方法名相同,参数列表不完全相同的方法,叫:重载。跟返回值类型无关;

final关键字

可以修饰:
成员变量:表示其变量拥有最终的值,不能被更改,成为"常量"。修饰基本数据类型:表示其值不能被修改。修饰引用数据类型,表示地址不能被修改;
成员方法:表示最终的方法。不能被重写;
类:   表示最终类。不能被继承;
局部变量:表示其值不能改变;区分:基本类型和引用类型;
方法形参:表示其值不能改变;区分:基本类型和引用类型;

多态

1.父类的引用指向子类的对象;
2.多态前提和体现
1).有继承关系
2).有方法重写
3).有父类引用指向子类对象
3.多态的转型:
1).自动转型:子类的引用转为父类的引用;Person p = new Student();
2).强制转型:父类的引用转为它所指向的子类对象的引用;Student stu = (Student)p;
3).在进行强制转型前,为保证安全,可以使用instanceof关键字进行判断:
if(p instanceof Student){
Student stu = (Student)p;
}
4.多态的好处:
1).提高了程序的维护性(由继承保证)
2).提高了程序的扩展性(由多态保证)
5.多态的弊端:
1).不能访问子类特有功能(可以向下转型)
6.多态时的访问规则
1).总体规则:访问的任何成员父类中必须要有,否则编译错误
例如:
class A{
int num = 10;
}
class B extends A{
int n = 20;
}
main(){
A a = new B();
System.out.println(a.n); //编译错误,父类中没有n
}
2).成员变量:如果子、父类中都有,访问的是“父类”的;
class A{
int num = 10;
}
class B extends A {
int num = 20;
}
main(){
A a = new B(); //多态
System.out.println(a.num); //打印10; 
}
   普通方法:如果子、父类中都有(重写),访问的是“子类”的;
class A{
void show(){
System.out.println("A-->show()");
}
}
class B extends A{
void show(){
System.out.println("B-->show()");
}
}
main(){
A a = new B();
a.show(); //打印:B-->show()(访问的是子类的show());
}
   静态方法:如果子、父类中都有(重写),访问的是“父类”的;

抽象类

1."抽象类"也是一个类;
2.有时,父类中的方法,会被每个子类重写,那么在父类中这个方法的方法体内容,就没有
意义了,这时,可以在父类中将此方法定义为"抽象方法":只有方法的定义,没有方法体;
需要使用关键字:abstract
3.如果一个类中包含了一个"抽象方法",那么这个类必须也要定义为"抽象类",仍然使用关键字:abstract
4.使用abstract关键字修饰;可以修饰“类”,可以修饰“成员方法”;
abstract class A{
abstract void show();
}
5.“抽象类”的特点:
1).不能被实例化,只能用于被继承;
2).可以包含:成员变量、构造方法、成员方法、抽象方法;
3).可以不包含抽象方法;
6.“抽象方法”的特点:
1).没有方法体;abstract void show();
2).必须被子类重写。除非子类也是个抽象类;
7.子类继承抽象类使用关键字:extends,仍然是单继承;
8.一个子类继承 了一个抽象类,必须实现抽象类中所有的抽象方法;
  否则子类也必须是抽象的。
例如:
abstract class A{
abstract void show();
}
class B extends A{  } //编译错误。类B不是抽象的,继承类抽象类必须重写抽象类中的所有抽象方法。
abstract class B extends A{  } //编译通过。类B没有重写父类中的抽象方法,但类B是抽象的。
9.抽象类中都可以定义什么?
1).成员变量;
2).实现的方法;
3).构造方法:作用:为成员属性赋值;
4).抽象方法;
10.抽象类的几个小问题:
a.一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
1).可以;
2).可以利用多态;
b.abstract关键字不能和哪些关键字共存:
1).private : abstract的方法就是需要被子类重写;一个private的方法不能被子类重写:
2).final:一个final的方法也不能被子类重写,所以与abstract冲突;
3).static:一个静态的方法,在没有对象的情况下,就会被分配空间。而一个抽象方法没有方法体,无法被分配空间。所以,一个抽象方法不能被定义为静态;

接口

0.如果一个类中包含的全部都是"抽象方法",可以将这个类定义为"接口";
1.使用interface关键字定义:只能修饰“类”:
interface IA{
}
2.“接口”的特点:
1).不能被实例化,没有构造方法,只能用于子类“实现”;
2).可以包含:
A.成员变量(常量):隐式的定义为:public static final。
              上述三个关键字中任何一个都可以不写,系统会自动添加;
例如:
interface IA{
public int num1 = 10; //OK
static final int num2 = 20; //OK
final int num3 = 30; //OK
public final num4 = 40; //OK
int num5 = 50; //OK
}
B.抽象方法:隐式的定义为:public abstract。可以省略,系统会自动添加
例如:
interface IA{
void show1(); //OK
public void show2(); //OK;
abstract void show3(); //OK;
}
3).接口的功能是:扩展功能;
3.子类实现接口使用关键字:implements
4.一个子类可以同时实现多个接口;不怕方法冲突,因为接口中的方法都是抽象方法;
interface IA{}
interface IB{}
class C implements IA,IB{ //OK的。
}
5.子类实现接口时,必须重写接口中所有的抽象方法,而且必须是public的--因为
                    接口中抽象方法的定义隐式的是public的。

例如:
interface IA{
void show();
}
class B implements IA{
void show(){  }       //编译错误。父接口的show()隐式的为public的,子类重写时必须是public的;
}

6.接口编译后一样会生成.class文件。
7.一个接口可以"继承"另一个或多个接口,使用关键字:extends ;
8.接口的作用:
1).多态;
2).Java中只允许单继承;可以通过同时实现多个接口达到"扩展功能"的目的;

多态的形式

1.父类的多态;
2.抽象类多态;
3.接口多态;

类与类,类与接口,接口与接口的关系

1.类与类:继承关系,关键字:extends ,只能单继承,但是可以多层继承
2.类与接口:实现关系,关键字:implements ,可以单实现,也可以多实现。还可以在继承一个类的同时实现多个接口
3.接口与接口:继承关系,关键字:extends,可以单继承,也可以多继承
例如:
interface IA{}
interface IB{}
interface IC extends IA,IB{} //OK的

抽象类和接口的区别

1.成员区别
1).抽象类 变量,常量;有抽象方法;抽象方法,非抽象方法
2).接口 常量;抽象方法
2.关系区别
1).类与类 继承,单继承
2).类与接口 实现,单实现,多实现
3).接口与接口 继承,单继承,多继承
3.设计理念区别
1).抽象类 被继承体现的是:”is a”的关系。共性功能
2).接口 被实现体现的是:”like a”的关系。扩展功能

类名、抽象类、接口作为形参和返回值

一.类名作为形参:
1.实参可以是:
1).此类对象的引用;
2).null;
3).此类子类对象的引用;
    二.抽象类作为形参:
1.实参可以是:
1).此类子类对象的引用;
2).null;
  三.接口作为形参:
1.实参可以是:
1).此接口子类对象的引用;
2).null;
    四.类名作为返回值:
1.可以返回的类型:
1).此类对象的引用;
2).null;
3).此类子类对象的引用;
2.可以用什么类型接收:
1).使用此类类型;
2).不能使用某个子类类型接收;
    五.抽象类作为返回值:
1.可以返回的类型:
1).null;
2).此类子类对象的引用;
2.可以用什么类型接收:
1).使用此类类型;(多态)
2).不能使用某个子类类型接收;
    六.接口作为返回值:
1.可以返回的类型:
1).null;
2).此接口子类对象的引用;
2.可以用什么类型接收:
1).使用此接口类型;(多态)
2).不能使用某个子类类型接收;

1.包就是一个文件夹;
2.不需要我们手动创建,Java中有语法可以创建包;
3.我们可以在定义类时,同时指定"包",编译后,编译器将把生成的class文件
编译到相应的包中;
4.定义包:使用关键字:package
   格式:package xxx.yyy.zzz;
         xxx是一级目录
yyy是二级目录
zzz是三级目录
     上述语句,会在当前项目根目录下创建以下文件夹:
%项目根目录%\xxx\yyy\zzz\Demo.class
5.包的级数:一般是三级目录:
第一级:国际顶级域名(com\cn)
第二级:公司名
第三级:项目名称(或者其它名称)
第四级:模块名(或者其它名称)
我们学习时一般使用三级包目录,以后工作时,根据公司的要求;
6.怎样访问其它包下的类:
两种方式:
1).使用全名限定的类名:带包名的类名
2).导包(常用):
1).使用关键字:import xxx.xxx.xxx.类名;
2).import语句一定要写在package之后;
   在class语句之前;
3).可以使用通配符(不建议):import xxx.xxx.xxx.*;//导入这个包下的所有的类(不包括子包和子包下的其他类)
7.定义包使用关键字:package;
1).注意事项:
A.package语句必须是程序的第一条可执行的代码
B.package语句在一个java文件中只能有一个
C.如果没有package,默认表示无包名
8.导入包使用关键字:import;
1).注意事项:
A.导入到最终的类;
B.可以使用通配符:*,只统配包下的类,不包括子包下的其它类;
C.在一个类文件中,可以有多条import语句;
D.import语句必须在package语句之后,在定义类之前;
9.package,import,class有没有顺序关系?
有:package-->import-->class

访问修饰符

1.用于限定“类”和“成员”被其它包下的其它类访问的;
2.四种访问修饰符:
1).public(公有):可以修饰类、成员。可以被任何包下的其它类访问;
2).protected(保护):可以修饰成员。可以被同包下的其它类访问。如果在包外
                                            只能被子类访问;
3).(默认):可以修饰类、成员。只能被包内的其它类访问;
4).private(私有):可以修饰成员。只能被类中的其它方法访问;
3.类及成员可用的修饰符:
1).类:
默认,public,final,abstract
我们自己定义:public居多
2).成员变量:
四种权限修饰符均可,final,static
我们自己定义:private居多
3).构造方法:
四种权限修饰符均可,其他不可
我们自己定义:public 居多
4).成员方法:
四种权限修饰符均可,fianl,static,abstract
我们自己定义:public居多

内部类

1.成员内部类:
1).定义在类体中,作为类的成员;
2).可以使用同类“成员方法”相同的修饰符;
3)它属于"类成员",所以,跟其它成员一样,可以使用访问修饰符
2).四种权限修饰符:public ,protected , (默认) ,private
static:静态的内部类,实例化时,不需要外部类先实例化;
2.局部内部类:
1).定义在某个方法或代码块内部;
2).不能使用“访问修饰符”,不能使用static修饰符;可以使用final和abstract
3).注意:局部内部类访问“局部变量”,要求局部变量必须是final的(常量);(重点)
4).局部内部类可以访问外部类的成员变量、成员方法;
3.匿名内部类:
1).就是内部类的简化写法。
2).前提:存在一个类或者接口
这里的类可以是具体类也可以是抽象类。
3).格式:
new 类名或者接口名() {重写方法;}
4).本质:
是一个继承了类或者实现了接口的子类匿名对象
5).场景:
//当我们想调用某个方法,但这个方法接收一个接口类型的实参;
//我们需要自定义一个子类,实现那个接口,这样很麻烦,而且这个子类只在这里用,其它
//地方用不到,所以就在调用这个方法的时候,定义一个"匿名内部类"。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值