文章目录
内部类
1. 什么是内部类 ?
- 简单理解,就是在一个类中 定义 另一个类。
- 如:
class A 中定义class B。 B 就是所谓的内部类。
- 如:
1.1 语法定义
- 就 定义位置 来说: 外面的叫外部类,里面的叫内部类,就相对而言。
// 外部类
修饰符 class 类名{
//在类的内部定义的类叫做内部类。
修饰符 class 类名{
}
}
1.2 内部类分类
- 分为四种:
- 成员内部类: 定义在成员位置,类中方法外。
- 局部内部类 :在局部位置 (即方法中) 。
- 静态内部类: 被关键字
static
修饰的内部类。 - 匿名内部类: 同匿名对象一样,没有名字,只为了调用一次。
1.3 内部类的特点
- 一个内部类对象可以访问创建它的外部类对象的内容,包括私有数据!
- 内部类不为同一包的其他类所见,具有很好的封装性;
- 内部类有效实现了“多重继承”,优化 java 单继承的缺陷。
2. 内,外部类之间的访问方式
- 一个内部类对象,可以访问创建它的外部类对象的内容,包括私有数据!
- 内外可以相互访问:
- 内部类 ,可以直接访问,外部类中的 成员变量和方法,包括
private
修饰的成员。 - 外部类,如果想访问内部类成员,就必须建立内部类的对象。
- 内部类 ,可以直接访问,外部类中的 成员变量和方法,包括
2.1 访问方式一(提倡)
- 外部类访问内部类,需要在外部类的方法中,创建内部类的对象, 来访问内部类。
public class MyClass {
public static void main(String[] args) {
OutClass o = new OutClass();
o.method();
}
}
//相对内部类来说,
class OutClass{//外部类
private String name="OutClass";//私有属性
private void test(){
System.out.println("外部类方法");
}
//相对外部类来说
class InterClass{ //内部类,可以使用private修饰
public void show(){
System.out.println(name);// 访问外部类的私有属性
test(); //也可以访问外部类私有方法
}
}
/*
访问方式一: 通过外部类方法,创建内部类对象访问
*/
public void method(){
InterClass i = new InterClass();
i.show();
}
}
-
输出结果:
OutClass 外部类方法
2.1 访问方式二(了解)
-
通过类调用直接访问。
- 访问方式:
外部类.内部类 变量名 = 外部对象.内部对象 ;
- 注意: 内部类不能使用
private
修饰。
public class MyClass { public static void main(String[] args) { //访问方式二: 外部类.内部类 变量名 = 外部类对象.内部类对象; //前提需要注意: 不能被 OutClass.InterClass oi = new OutClass().new InterClass(); oi.show(); } } //相对内部类来说, class OutClass{//外部类 private String name="OutClass";//私有属性 private void test(){ System.out.println("外部类方法"); } //相对外部类来说 class InterClass{ //如果使用 外内结合对象的方式访问 内部类不能使用private修饰。 public void show(){ System.out.println(name);// 访问外部类的私有属性 test(); //也可以访问外部类私有方法 } } }
- 访问方式:
-
输出结果:
OutClass 外部类方法
3. 成员内部类
3.1 private修饰内部类
-
内部类不为同一包的其他类所见,具有很好的封装性;
-
内部类被
private
修饰,目的,就是 隐藏自己(封装) 不想被外界发现或者使用! -
例如生活中:
- 人类,最重要的器官就是心脏,心脏就需要心跳。当心脏问题时,只能交给专业的人去治疗。
public class MyClass { public static void main(String[] args) { //1. 如果内部类使用了private修饰,访问方式就使用第一种 // 外部类创建方法调用内部类对象。 Person p = new Person(); p.make_Heart("荒漠屠夫"); } } class Person{ //2.为啥要私有?这样就可以封装起来 private class Heart{ //内部类就一个方法,心跳方法 private void heartbeat(){ //很复杂的业务处理机制... System.out.println("心脏在跳动... "); } } //2.心脏真出问题了需要治疗, // 意思: 提供一个访问内部类方法 public void make_Heart(String name){ //通过if判断控制 if (name.equals("医生")){ new Heart().heartbeat();//创建内部类对象,访问内部类方法 }else { System.out.println("不符合条件"); } } }
-
输出结果:
不符合条件
3.2 静态内部类
3.2.1 定义
-
被关键字
static
修饰内部类,就是静态内部类,并且static
只能修饰内部类。 -
静态内部类 和 普通内部类的区别:
- 普通内部类 :不允许有静态属性和静态方法;
- 静态内部类: 可以声明普通成员变量 和 方法。但是静态内部类中,。
-
普通方法访问不了外部类属性,因为需要将 静态内部类中所有,看做一个整体。
- 这样就需要遵循
static
特点,静态只能访问静态。
public static void main(String[] args) { //第二种访问方式,没有private修饰。 Person.Heart ph = new Person.Heart();// 静态的访问方式 ph.heartbeat(); } } class Person{ private int num=60; //外部类成员属性 //1.静态内部类中的普通方法!为啥访问不了外部类属性!? //解答:相当于把静态内部类看成一个整体,这样访问外部属性的时候,也需要遵循静态访问静态的原则。 // 但是内部成员来说,还是遵守static 关键字的使用!!! public class MyClass { //内部类 static class Heart{ //static 静态内部类 public void heartbeat(){ //静态类中可以有普通方法 System.out.println("每分钟跳"+num); //获取外部类属性? } } }
- 这样就需要遵循
-
输出结果:
Error:(23, 42) java: 无法从静态上下文中引用非静态 变量 name
3.2.1 静态内部类访问方法和属性
- 必须把
static
修饰的内部类看做一个整体,遵循static
访问特点,- 静态只能访问静态。
- 非静态可以访问静态和非静态。
public class MyClass { public static void main(String[] args) { //1. 如果内部类使用了private修饰,访问方式就使用第一种 // 外部类创建方法调用内部类对象。 Person p = new Person(); p.make_Heart("医生"); //2. 没有被private 修饰内部类 new Person.Heart().heartbeat();//如可以使用链式访问 } } class Person{ private int num=60; static String speed="20秒"; //2.为啥要私有?这样就可以封装起来 static class Heart{ //内部类就一个方法,心跳方法 public void heartbeat(){ //静态中的普通方法也可以静态属性 System.out.println("心脏在跳动... "+speed); } static void blood(){ System.out.println("血液开始流动,每 "+speed+" 循环一次"); //静态方法调用静态属性 } } public void make_Heart(String name){ if (name.equals("医生")){ Heart h = new Heart(); h.heartbeat(); h.blood(); // 调用静态 }else { System.out.println("不符合条件"); } } }
-
输出结果:
心脏在跳动... 20秒 血液开始流动,每 20秒 循环一次
4. 局部内部类(了解即可)
- 在方法里的类。不常见
- 该内部类权限必须是
public
。
- 该内部类权限必须是
public class MyClass {
public static void main(String[] args) {
new Person().heartbeat();//调用外部类方法,在通过方法调用内部类方法
}
}
class Person{
public void heartbeat(){
//在方法中的内部类,权限就是 public
class Blood{
public void speed(){
System.out.println("在心脏中的血液... ");
}
}
//使用匿名对象,调用一次内部类
new Blood().speed();
}
}
5. 匿名内部类
-
同 匿名对象 一样,没有名字 的内部类。就是为了调用一次。
-
语法结构:
new 接口/类名(){ //需要花括号 1.重写方法 2.自定义方法 };
-
匿名对象和匿名内部类通常一起使用,属于局部内部类!
public class MyClass2 {
public static void main(String[] args) {
Person2 p = new Person2();
p.heart();
p.blood();
}
}
class Person2{
//调用接口
public void heart(){
//1. 匿名内部类调用接口
new Make(
) {
@Override
public void heartbeat(String name) {
if (name.equals("医生")){
System.out.println("请开始手术");
}else {
System.out.println("需要医生");
}
}
}.heartbeat("医生"); //相当于调用方法传递参数。
}
//2.调用普通方法
public void blood(){
//普通类也能调用。但是需要手动重写方法
new Make2(){
@Override
public void blood() {
System.out.println("血液流动中.....");
}
}.blood();
}
}
//1.接口
interface Make{
public abstract void heartbeat(String name);//治疗薪资
}
//2.普通方法
class Make2{
public void blood(){
System.out.println("血液流动");
}
}
//3.抽象类,自己动手
6 使用内部类实现“多继承”。
- 内部类有效实现了 “多重继承” ,优化 java 单继承的缺陷。
- 例如:手艺的传承,爷爷会一种,爸爸会一种, 儿子正常来说应该会两种。
public class MyClass {
public static void main(String[] args) {
Son son = new Son();
son.doThing();
//1. 调用爷爷的方法
Son.Myself sm = new Son().new Myself();
sm.doThing();//调用爷爷的。
//1.使用多态形
Person.method(new Father()); //静态方法类名直接调用
}
}
interface Person{
public void doThing();
//查看会什么功能。
static void method(Person p){
p.doThing();
}
}
class Grandpa implements Person{
public void doThing(){
System.out.println("会开摩托车");
}
}
class Father implements Person{
public void doThing(){
System.out.println("会开汽车");
}
}
//Son类能继承Father类和Grandpa类么?
class Son extends Father{
//1.使用内部类实现爷爷的方法
class Myself extends Grandpa {
@Override
public void doThing() {
super.doThing(); //调用他爷爷的方法
}
}
@Override
public void doThing() {
System.out.println("会骑电动车");
}
}