07面向对象编程

面向对象思想

[外链图片转存失败(img-9r67kzRh-1567685527122)(D:\每日总结\图片1.png)]
面向对象三大特性:封装,继承,多态

类和对象

如何定义一个类:
格式
[访问权限修饰符] class 类名 {
属性 (成员变量/ 全局变量)
行为 (成员方法)
}
类的理解: (引用类型)
1.类是用来描述现实世界所有的事物,在Java中实现信息化
2.类是抽象的,抽取多个对象相像的部分
3.类是一个模板,是属性和行为的集合
4.类是Java当中最基本的组成单位
5.Java当中使用 class 来定义类
6.类的本质就是 组织代码(方法) 封装数据(属性)
对象的理解
1.对象是客观存在的
2.万事万物皆对象
3.对象是通过类的模板创建的,先定义类,再创建对象
4.对象又称 实例/引用/变量

创建对象的格式:
类名 对象名 = new 类名();

如何访问一个对象的成员变量/成员方法?
通过 .(指针) 来访问

**检查您写的代码是否满足面向对象思想: **
在 main 方法中不断地创建对象,调用对象的成员变量,成员方法,而不出现任何的逻辑计算代码.

局部变量和成员

成员变量又称为全局变量

面试题: 成员变量和局部变量的区别?
1.定义的位置不同 :happy:
局部变量: 定义在方法体内或者方法的声明上
成员变量: 定义在类体以内,方法体以外
2.在内存中位置不同:happy:
局部变量: 在栈区开辟内存
成员变量: 在堆区分配内存
3.初始化值不同:happy:
局部变量: 没有默认值,需要自己给出默认值,否则直接使用会编译报错
成员变量: 因为在堆区,堆区是有默认值,默认值规则:
byte short int long 默认值 0
float double 默认值 0.0
char 默认值 ‘\u0000’ 就是一个空字符
boolean 默认值 false
引用类型 默认值 null
4.变量的生命周期不同 :happy:
【生命周期: 表示一个变量从创建到销毁的全过程】
局部变量: 随着方法的调用而创建,方法调用结束而销毁
成员变量: 随着对象的创建而创建,具体销毁时间取决垃圾回收期空闲的时候回收的时间
5.:happy:如果成员变量和局部变量重名,就近原则,如果要区分局部变量和成员变量,可以使用关键字 this

值传递和引用传递

关于类的值传递和引用传递的问题

引用传递:
类 接口 数组

?值传递本质传递的是数值本身,而引用传递传递的是地址,

  • 如果多个引用指向同一个堆区的空间地址,任何一个引用修改了堆区的内容,都会影响到所有的引用

匿名对象

匿名对象 --> 没有名字的对象,是一种对象的简化形式

匿名对象的特点:
1.既然是对象,就可以调用属性和方法
2.匿名对象只能够使用一次,如果需要使用多次,还是需要带有名字的对象
3.匿名对象一旦使用完毕,立刻成为垃圾对象,等待垃圾回收期空闲的时候回收,提供了效率和安全性,节约内存资源
Java里面使用匿名对象主要是为了简化编程
节约内存资源主要使用在Android
4.匿名对象作为形参传入的时候也是非常方便的

垃圾对象

垃圾对象: 没有指针指向堆区空间的对象

什么时候会成员垃圾对象?
1.对象赋值为 null
2.对象被重新分配内存空间
3.匿名对象使用完毕
4.对象所在的方法调用结束

如何来回收垃圾? 不由我们管理
启动垃圾回收器
System.gc();
通知垃圾回收期回收垃圾对象 finalize() 是Object类的一个方法
System.runFinalization();

public class OOPDemo05 {
	public static void main(String[] args) {
		Student s = new Student()
		// 1.对象赋值为 null
		// s = null;
		// 2.对象被重新分配内存空间
		s = new Student();
		
		// 3.匿名对象使用完毕
		// new Student().study();
		
		// 启动垃圾回收器
		System.gc();
		
		// 通知垃圾回收期回收垃圾对象  finalize() 
		System.runFinalization();
		
	}
}

封装/private关键字

为什么要学习封装
1、不希望外界直接访问我的成员,提高了成员的安全性,
2、不希望外界随意修改成员的值
eg:如果成员变量前边加了一个private,那么我只能通过get和set对该成员进行赋值和获取值,更安全
封装的步骤:
1、给需要封装的属性加上private关键字,即访问权限修饰符
2、给封装的属性(成员)加上set和get方法
3、在读写方法中对成员做数据校验(看需求,一般省略不写,看需求)

注意?:

在成员位置/全局位置是不能够书写逻辑计算代码,只能够定义成员,如下所示,if语句会编译报错,因为他处的位置在成员变量和方法之间,即又不是在方法里,所以写方法不对,应该写在一个方法里
eg:
`

class Student {
private String name;
private int age;

if (outAge < 0 || outAge > 120) {
		System.out.println("年龄不在人类的范围之内!!!");
	} else {
		age = outAge;
	}

public void study() {
	System.out.println("Student.study()");
}`	

类的最基本组成
class 类名
成员变量;
成员方法;
读写方法(get/set方法)[^Alt+shift+s,再按R,生成该方法快捷键]:
封装的本质:就是访问权限修饰符
访问权限修饰符就是给成员对外界的一个访问级别

this关键字

为什么需要学习this关键字
1、this 代表 现实世界 代词 “我的” 的概念
2、当成员变量和局部变量重名的时候使用 this
this概述:
this代指当前对象,本质是一个地址,变量和当前对象指向同一个堆区的空间
this的特点:
1.每次new一个对象,都会创建一个变量 this指向同一堆区的空间
2.this代指当前对象,谁new或者谁调用方法,this就代指谁
3.this只能够出现类的内部类
4.static上下文中不能够出现this或者super(后面讲解 static和继承 的时候详细讲解)因为this代表的是调用这个函数的对象的引用,而静态方法是属于类的,不属于对象,静态方法成功加载后,对象还不一定存在 2. 在问题之前先讲super的用法:1.super的用法跟this类似,this代表对本类对象的引用,指向本类已经创建的对象;而super代表对父类对象的引用,指向父类对象;2.静态优先于对象存在;3.由上面的1.和2.知:因为静态优先于对象存在,所以方法被静态修饰之后方法先存在,而方法里面要用到super指向的父类对象,但是所需的父类引用对象晚于该方法出现,也就是super所指向的对象没有,当然就会出错。综上,静态方法中不可以出现super关键字。 3. 首先你要明白对象和类的区别。 this和super是属于对象范畴的东西,而静态方法是属于类范畴的东西所有的成员方法,都有一个默认的的参数this(即使是无参的方法),只要是成员方法,编译器就会给你加上this这个参数
5.默认在类的内部访问成员默认可以省略this
应用场景:
1.当局部变量和成员变量重名
2.当需要在类的内部访问类的成员
3.访问本类构造方法的时候可以使用this (后面讲解构造方法的时候详细讲解)[外链图片转存失败(img-MfWkq8sZ-1567685527123)(D:\每日总结\Snipaste_2019-08-09_20-35-25.png)]

构造方法

为什么需要学习构造方法
通过一个一个初始化成员变量非常麻烦, Java设计了构造方法
构造方法的格式:
[访问权限修饰符] 方法名(参数列表) {
方法体; 帮助我们快速初始化成员
// return;
}
**注意: **
1.构造方法的方法名必须和类名保持一致,连void都没有
2.构造方法也可以方法重载
3.构造方法不能够递归
4.如果我们自己没有编写构造方法,那么系统会帮我们书写一个无参构造方法
5.一旦我们写了一个带参构造方法,那么就会覆盖系统的无参构造方法,如果这个时候使用无参构造方法,那么编译会报错
6.习惯: 一般建议写上无参构造方法
如果没有无参构造方法,很多框架会在运行的时候报错
框架很多时候都是利用反射技术,反射技术可以动态创建对象,动态创建对象都是调用无参构造方法
7.无参构造方法的作用
a.反射框架调用
b.初始化一些固定成员
8、一旦写了构造方法,那么他的子类构造方法一定得写super(),不然会报错

目前初始化成员的方法有几种:
1.set方法
2.构造方法
3.普通方法 init
构造方法和普通方法的区别:
1.构造方法的方法名必须和类名保持一致,连void都没有
2.构造方法不能够递归
3.构造方法除了可以初始化成员,还可以结合 this super new 关键字使用
4、?构造方法不能用new一个对象,然后对象.构造方法名,错误
eg:
对:Circle1 c=new Circle1(new Point1(0,0),1);
错:Circle1 c=new Circle1(); c.Circle(new Point1(0,0),1)
因为Circle是构造方法,不能直接调用

static 关键字

为什么要学习static关键字
多个对象共享同一分数据,可以使用static修饰
static的特点:
1.静态变量属于类的,不属于具体的对象
2.访问静态成员的方式:
The static field Student.nationality should be accessed in a static way
1.通过对象访问静态成员 (不建议)
2.通过类访问 (推荐)
3.静态变量又称为 类变量,不使用static修饰的变量成为非静态变量
4.静态即可以修饰成员变量,还可以修饰方法
static 修饰方法的好处 可以方便外界在不创建对象的情况下直接调用方法,执行功能
static 修饰方法常用来编写工具类 Utils Objects Arrays
工具类的编写步骤:?
a. 构造方法私有
b. 所有成员方法添加 static 关键字
5.静态环境下不能够访问非静态变量,非静态环境下可以访问静态变量
Cannot make a static reference to the non-static field name
6.静态修饰的变量在类加载的时候加载到方法区的静态区
7.静态还可以修饰 代码块 和 类(内部类)

代码块(初学难点)

 代码块: 使用 {} 包裹起来的代码就称为代码块

代码块的分类:
1.构造代码块:
定义在成员位置,用于抽取多个构造方法中的共性代码,从而达到简化代码的目的
执行时机: 每次访问构造方法之前执行,可以执行多次
2.局部代码块:
定义在局部位置,方法体内,限定局部变量的作用域
3.静态代码块:
使用 static 修饰的代码块
静态代码块无论创建多少个对象,都是优于构造方法和构造代码块之前执行,并且只执行一次
执行时机: 在类加载的时候执行
类加载时机: 类中的成员第一使用的时候

**执行顺序: 静态代码块 > 构造代码块 > 构造方法**
4.<u>同步代码块:</u>
	多线程后面讲解

package关键字

为什么要学习包?
方便管理文件,解决了同包下类重名问题
命名规范
所有单词小写,每一个单词使用.号隔开,公司域名反写
包声明格式:
package 包名1.包名2.包名3…包名n;
包的导入格式:
import 包名1.包名2;
包的特点:
1、同包下的类不需要导包
2、java.lang包下的所有类不需要导包,系统会自动帮我们导入
3、如果一个类没有导入包,那么这个类默认是一个孤立的类,其他包无法
访问该包下所有类,所以一般先建包再建类
4、包的声明必须出现在首行代码,有且只有一句
5、如果在同一个类下使用两个不同包下的同名类,需要使用类路径
6、在书写类名的时候不要和系统的类重名
7、如果需要导入一个包下多个类或所有类,可以使用通配符*
JDK一些常见的包:
java.lang:
包含一些语言核心类,如String、Math、Interger、System、Thread
Java.awt
包含了构成抽象窗口工具类(abstract、windows、toolkits)多个类
java.net
包含了执行与网络相关的操作的类
java.io
包含了提供多种输入/输出功能的类
java.util
包含了一些工具类,如定义系统特性、使用与日期日历相关的函数
快捷键:
Ctrl +Shift+O 一键导包
Ctrl+1 单个导包

import关键字

继承

为什么要学习继承?
简化了代码/提高了程序可扩展性和可维护性
OOA:面向对象分析,分析一共涉及到多少个对象,多少个包
OOD:类与类之间的关系
a:继承A is a B
b:组合A has a B
OOP:在主方法中,不断创建对象,使用对象,指挥对象做事情[调用方法属性]
继承的本质:
类是对一批对象的抽象,继承是对一批类的抽象,继承本质就是抽取多个类共性代码
继承的格式
class子类/派生类 extends 父类/基类/超类
继承的好处
1、简化了代码,把重复的代码提取到了一个class里面。子类继承他
2、提高了代码的扩展性和可维护性
3、继承是多态的必要条件(后面讲解多态)
继承的缺点
1、违背了高类聚,低耦合的设计原则,继承是一把双刃剑
继承慎用【牵一发动全身】,继承的缺点是无法弥补的
以后尽量使用接口 【面向接口编程】
继承的注意事项
1、继承不支持多继承,但支持多层继承
2、如果一个父类使用了private修饰一个属性,那么他的子类就访问不了这个属性
3、如果子类继承了父类的属性和方法,那么子类还可以有自己的属性和方法
如果子类覆盖了父类属性,那么子类优先
4、子类不能够继承父类的构造方法
如何来使用继承
1先写子类
2、观察多个子类之间是否存在共性代码
3、定义父类,保存共性代码,将子类继承父类
4、将子类共性代码删除
5、验证:检查子类和父类之间是否满足is a 关系
什么时候继承
1、抽取共性代码
2、当设计一个非常复杂的类的时候可以考虑使用继承
3、当使用多态的时候必不可少的需要使用到继承

super关键字

为什么要学习super?
能够帮助子类快速初始化从父类继承下来的成员,从而简化代码
super的定义:
this:代表当前的对象,创建任何一个对象,都会创建一个this引用和该对象只想要同一个堆区的空间,this就是一个地址
super:代表父类存储空间的标识(标识指能通过super访问父类成员,但super不能代替父类成员),super可以通过创建这个标识访问父类的成员,super可以理解为父类对象(但不能代表父类对象),this可以作为参数传入到方法的形参中,super不可以

super和this访问成员的特点:
成员变量
this.成员变量
super.成员变量
成员方法
this.成员方法
super.成员方法
构造方法
this(参数列表)
super(参数列表)

**1.为什么访问子类构造方法之前会访问父类构造方法? **
访问父类无参构造方法导致所有的父类的静态成员和静态代码块被加载,最终根类Object类的注册方法也会被加载
2.访问子类构造方法会访问父类构造方法,那么会不会创建子类对象的同时创建父类对象?
不会 使用super/this方法构造方法就相当于调用普通方法,需要创建对象访问构造方法必须结合 new
3.任何一个构造方法第一句都会先访问父类无参构造方法
4.this super 访问构造方法必须出现第一句
5.this 和 super 访问构造方法不能够共存
6.super可以访问父类的成员
7.static上下文不能够出现this super

面试题

public class Demo4 {	
	public static void main(String[] args) {
		Zi zi = new Zi();
		System.out.println(zi.num);
	}
}
class Fu {
	int num = 10;	
	/*public Fu() {
	}	*/
		public Fu(int num) {//为什么此处重载之后,会覆盖无参构造函数,方法重载的时候定义了多个方法,为什么没有被一一覆盖
			this.num = num;
		}
	}
	class Zi extends Fu {
		int num = 20;
	}

访问权限修饰符

表现:
用于提高数据的安全性,控制外界的访问级别,是封装的具体体现

访问权限修饰符分为:
public protected default[表示一种没有加以任何修饰的状态] private

访问权限修饰符的特点:
1.public 对所有类可见 (项目可见性)
2.protected 对同包下以及同包下的子类可见 (子类可见性)
3.default 对同包下可见 (包可见性)
4.private 仅对本类可见 (类可见性)
5.访问权限修饰符 可以修饰 成员变量 成员方法 构造方法, 也可以修饰类,只有 public default 可以
但是内部类可以使用 private protected 修饰
6.访问权限修饰符的 宽严 关系
public > protected > default > private
7.我们经常提到的封装就是通过 访问权限修饰符 实现

方法重写

 为什么需要学习方法重写? --> 父类的功能实现无法满足子类的需求,需要重写

@Override 表示重写的一个注解

重写的特点:
1.发生在具有子父类两个关系的类中
2.方法名称相同
3.参数的列表完全相同
4.返回值类型可以相同也可以是其子类
5.访问权限修饰符不能够严于父类
public > protected > default > private

​ 6.重写是多态的必要条件
​ 7.抛出的异常不能比父类的异常更大 (后面讲解异常的时候详细讲解)
​ 8.私有方法不能被重写,因为私有方法不能够被继承,所以谈不上重写
​ 9.不能使用static
​ 26. 什么样的方法不能被重写( B )。
​ A.私有(private)方法//无法继承,怎么谈重写- B.最终(final)方法
​ C.受保护(protected)的方法 D.以上都不对
面试题: 重写和重载的区别

抽象类

概念:在JAVA中,如果一个没有方法体,没有实现的方法定义为抽象方法,一个类中如果出现了抽象方法,那么该类一定是个抽象类

抽象类的特点
1、抽象类使用abstract关键字修饰
2、有一个抽象方法的类一定是抽象类
3、一个抽象类可以没有抽象方法
4、没有抽象方法的抽象类有意义,防止外界创建对象
防止外界创建对象的方式有4种:
a、构造方法私有
b、抽象类
c、接口
d、内部类
5、抽象方法不能够实例
6、如果想要实例化抽象类,那么可以利用多态进行“实例”。
7、抽象类可以创建匿名内部类对象
匿名内部类格式:
new 类名(){
重写方法
}
8、抽象类的子类特点:
a、如果一个子类想要继承抽象类,就必须实现抽象类中的所有抽象方法
b、如果子类不想实现抽象类中的抽象方法,子类必须升级为抽象类
9、抽象类和普通类的区别:
抽象类中是否有 常量 成员变量 成员方法 构造方法 静态方法
常量 静态方法 直接类名方法
构造方法:帮助子类初始化父类继承下去的成员
10、private final native static protected public 哪些可以修饰抽象方法,哪些不可以,说出原因
private:私有化,但抽象方法是为子类服务的,和抽象方法冲突
final和native:
protected和public:可以和抽象方法共存
11、抽象方法的本质就是一个彻头彻尾的服务类,所有的成员都给子类使用,自己不能实例化,抽象类可以是一个模板
声明抽象方法,大括号可有可无

final关键字

final表示最终的
特点:
1.final修饰类不能够被子类继承
2.final修饰的变量表示常量
常量不能够被二次赋值

final修饰
成员变量
因为成员变量默认值是0,不能够被二次赋值
因为常量是在常量池中,不在堆区,所以没有默认值
局部变量
局部变量没有给默认值,所以不能被二次赋值

3.final修饰成员方法
不能够被子类重写
常用的final类有哪些? String Math

接口

在生活中接口是一种规范,接口是灵活的,可以扩展功能

接口本来就是为了充分利用多态特性来增加框架扩展性,宏观理解:接口开发
应用:后台接口开发,前端界面
从微观理解:类似于方法Java里面的interface

Java当中的接口:接口的本质就是一种标准/规范/声明
接口的格式:
interface 接口名{
常量 和抽象方法的集合
void play();此处不能有大括号包含的内容
注意:在JDK之后还可以有静态方法和默认方法
}
接口的实现类格式:
class 接口名 implements 接口名{
//实现接口中所有的抽象方法
}
接口的特点:
1、使用interface关键字修饰
2、接口是常量和抽象方法的集合,在JDK1.8后还可以有静态方法和默认方法
3、接口中的常量默认省略 public static final
4、接口中的方法默认省略 public abstract
5、如果想要实例化一个接口,那么就必须多态【接口多态】
6、接口的子类特点:
a、如果一个类想要实现一个接口,就必须实现该接口中所有的抽象方法
b、如果一个类不想实现接口的方法,那么该类升级定义为接口
7、接口是一种规范,是灵活的,可以扩展功能
8、接口和抽象类的区别:
父类是普通类的 是模板,父类是抽象类的 是部分模板,部分规范,父类是接口的时候,就是完全规范(即实现全部接口的方法)
9、类和类:单继承,不能多继承,不能多实现
类和接口:多实现,不能够多继承
接口和接口:多继承,不能多实现
10、什么时候使用接口?什么时候使用继承?
当抽取多个共性代码或者设计复杂类的时候使用继承,
当我重新开始编写一些简单的功能或者制定一些标准的时候使用接口
开发中一般采用面向接口编程,抽象类是模板,接口是规范
11、面向接口编程
集合框架 collection List

多态

多态的必要条件:
1、必须存在继承
2、必须存在方法重写
3、父类引用指向子类对象?(重难点,不太容易)
多态访问成员的特点:(非常重点,难理解)?
成员变量:编译时期看左边类型,运行时期看左边类型(左左)结合值传递知识点理解
成员方法:编译时看左边类型,运行时看右边类型 (左编译,右执行)结合引用传递知识点理解
构造方法:帮助子类初始化父类继承过来的成员
静态方法:编译时期看左边类型,运行时器看左边类型(左左)
多态
多态的缺点以及解决方法
缺点: 通过多态的父类引用无法访问子类所特有的方法

向上转型(自动转换)
格式:<父类型> <引用变量名> = new <子类型>();
特点:
子类转为父类 父类的引用指向子类对象。自动进行类型转换
此时通过父类引用变量调用的方法是子类覆盖或继承父类的方法
此时通过父类引用变量无法调用子类特有的属性和方法
向下转型(强制转换)
格式:<子类型> <引用变量名> = (<子类型> )<父类型的引用变量>;
特点:
父类转为子类,父类引用转为子类对象。理解为强制类型转换
在向下转型的过程中,如果没有转换为真实子类类型,会出现类型转换异常

ClassCastException
异常名称: 类型转换异常
产生原因: 在向下转型的过程中没有转换成真实的类型
解决办法: 对父类的所有子类做逐一类型判断

instanceof关键字
格式: 左边对象 instanceof 右边类
作用: 判断左边对象是否属于右边类的实例,是返回true,不是返回false

目前我们知道使用向下转型 + instanceof关键字能够解决多态的缺点
但是我们清楚 如果需要对父类的所有子类做逐一判断,可能存在安全隐患或者违反开闭原则
但是还有一个Object类,该类有无数个子类,所以如果父类引用是Object,那么安全隐患永远存在
后期考虑使用泛型改进

多态的应用_继承多态_接口多态

多态的两种实现方式
使用父类作为方法形参实现多态
使用父类作为方法返回值实现多态

当这个作为参数的父类是普通类或者抽象类时,构成继承多态
当这个作为参数的父类是一个接口时,构成接口多态

多态作为形参

形式参数
基本类型(前面讲过,不解释)
引用类型
普通类
当一个形参希望我们传入的是一个普通类时,我们实际上传入的是该类的对象/匿名对象
抽象类
当一个形参希望我们传入的是一个抽象类时,我们实际上传入的是该类的子类对象/子类匿名对象
接口
当一个形参希望我们传入的是一个接口时,我们实际上传入的是该类的实现类对象/实现类匿名对象

多态作为返回值
返回值类型
基本类型(前面讲过,不解释)
引用类型
普通类
当一个方法的返回值是一个普通的类时,实际上返回的是该类的对象,我们可以使用该类的对象接收
抽象类
当一个方法的返回值是一个抽象类时,实际上返回的是该抽象类的子类对象,我们可以使用该抽象类接收
接口
当一个方法的返回值是一个接口时,实际上返回的是该接口的实现类对象,我们可以使用接口接收

	当方法的返回值类型是引用类型的时候,可以使用链式调用

内部类

为什么需要有内部类、
提高类的安全性
内部类的概念
将类定义在类的内部,那么该类就成为内部类
注意: 内部类是一个相对的概念,如果A类中有一个B类,那么A类相对于B类来说就是外部类,那么B类相对于A类来说就是内部类
内部类的分类:
1、成员内部类
2、局部内部类
3、静态内部类
4、匿名内部类
内部类的特点:
1、内部类可以直接访问外部类的特点
2、外部类如果想要访问内部类成员,必须创建内部类对象
3、内部类如果编译后生成2个字节码文件,格式如下
外部类 内 部 类 . c l a s s O u t e r C l a s s 内部类.class OuterClass .classOuterClassInnerClass.class
4、要访问内部类成员非常麻烦,比如new Outer().inner.num,造成的程序耦合性增高,可读性降低,所以内部类要慎用
5、内部类不能定义静态变量,如果需要定义,那么需要使用final修饰

成员内部类

掌握如何访问成员内部类的成员
格式:
外部类类名.内部类类名 对象名=外部类对象.内部类对象

局部内部类

eg:
~~~
class OuterClass4{	
class InnerClass{		
}
public void show() {	
	int num = 50;
	class InnerClass{//局部
		private int num = 100;
		public void method() {
			System.out.println(num);
		}
}}
~~~

静态内部类

成员内部类也可以用static 和private 修饰
访问格式:
外部类类名.内部类类名 对象名 =new 外部类类名.内部类类名
静态内部类主要成员是静态成员,可以方便调用,同时提高类的安全性
静态内部类可以有静态成员和非静态成员

成员私有内部类

利用private 修饰内布类
更加提高了内部类的安全性

匿名内部类

本质:就是一个子类匿名对象
特点:
1、是一个子类,eg普通类,抽象类,接口
2、没有名字的子类
3、是一个对象
格式:
new 类或父类/抽象类/接口(){
//重写方法
}
匿名内部类的本质是一个继承(父类)或者实现(接口)的子类匿名对象

	public static void main(String[] args) {
		new Student();
		// 如果子类是普通类
		// 匿名对象
		new Student().show();
		// 匿名子类对象
		new Student() {}.show();
		// 重写了show方法的匿名子类对象
		new Student(){
			public void show() {
				System.out.println("Zi Student.show()");
			}
		}.show();
		// 利用多态
		AbsTeacher teacher = new PrimaryTeacher();
		teacher.method();
		// 匿名内部类 + 多态
		// 这是一个继承并且重写method方法的AbsTeacher的子类匿名对象
		new AbsTeacher() {
			@Override
			public void method() {
				
				System.out.println("Zi PrimaryTeacher.method()");
			}	
		}.method();

注意:


public class InnerClassDemo {
 
	class InnerClass{
		//1、这样是可以的,这样编译器会在编译的时候就将这种语句变成常量值(也就是说可以定义所有的static final + 基本数据类型)
		static final int i = 50;
		//2、这样不可以,虽然也为static final 但是说到底还是个变量对象,所以不可以这样
		static final String str = new String("");
		//3、与上相同
		static InnerClass innerClass = new InnerClass();
	}

就第三种情况来说,那么根据初始化的流程我们知道,在类加载的时候,static变量就会被初始化,那么我们InnerClass对象在没有InnerClassDemo这个对象的时候便生成了。。这样这个成员内部类就脱离了外部类的掌控,不需要外部类的对象就可以生成内部类的对象,这与成员内部类的定义就相驳了,因为我们知道成员内部类的对象必须是现有外部类的对象才能创建,并且是绑定在一起的,所以成员内部类不可以定义静态变量。
() {
@Override
public void method() {

			System.out.println("Zi PrimaryTeacher.method()");
		}	
	}.method();

注意:

public class InnerClassDemo {

class InnerClass{
	//1、这样是可以的,这样编译器会在编译的时候就将这种语句变成常量值(也就是说可以定义所有的static final + 基本数据类型)
	static final int i = 50;
	//2、这样不可以,虽然也为static final 但是说到底还是个变量对象,所以不可以这样
	static final String str = new String("");
	//3、与上相同
	static InnerClass innerClass = new InnerClass();
}
就第三种情况来说,那么根据初始化的流程我们知道,在类加载的时候,static变量就会被初始化,那么我们InnerClass对象在没有InnerClassDemo这个对象的时候便生成了。。这样这个成员内部类就脱离了外部类的掌控,不需要外部类的对象就可以生成内部类的对象,这与成员内部类的定义就相驳了,因为我们知道成员内部类的对象必须是现有外部类的对象才能创建,并且是绑定在一起的,所以成员内部类不可以定义静态变量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值