how2j.cn


工具版本兼容问题
内部类分为四种:
非静态内部类
静态内部类
匿名类
本地类


本视频是解读性视频,所以希望您已经看过了本知识点的内容,并且编写了相应的代码之后,带着疑问来观看,这样收获才多。 不建议一开始就观看视频



16分41秒
本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)



步骤 1 : 非静态内部类   
步骤 2 : 静态内部类   
步骤 3 : 匿名类   
步骤 4 : 本地类   
步骤 5 : 在匿名类中使用外部的局部变量   
步骤 6 : 练习-内部类   
步骤 7 : 答案-内部类   

步骤 1 :

非静态内部类

edit edit
非静态内部类 BattleScore “战斗成绩”
非静态内部类可以直接在一个类里面定义

比如:
战斗成绩只有在一个英雄对象存在的时候才有意义
所以实例化BattleScore 的时候,必须建立在一个存在的英雄的基础上
语法: new 外部类().new 内部类()
作为Hero的非静态内部类,是可以直接访问外部类的private实例属性name的
package charactor; public class Hero { private String name; // 姓名 float hp; // 血量 float armor; // 护甲 int moveSpeed; // 移动速度 // 非静态内部类,只有一个外部类对象存在的时候,才有意义 // 战斗成绩只有在一个英雄对象存在的时候才有意义 class BattleScore { int kill; int die; int assit; public void legendary() { if (kill >= 8) System.out.println(name + "超神!"); else System.out.println(name + "尚未超神!"); } } public static void main(String[] args) { Hero garen = new Hero(); garen.name = "盖伦"; // 实例化内部类 // BattleScore对象只有在一个英雄对象存在的时候才有意义 // 所以其实例化必须建立在一个外部类对象的基础之上 BattleScore score = garen.new BattleScore(); score.kill = 9; score.legendary(); } }
在一个类里面声明一个静态内部类
比如敌方水晶,当敌方水晶没有血的时候,己方所有英雄都取得胜利,而不只是某一个具体的英雄取得胜利。
与非静态内部类不同,静态内部类水晶类的实例化 不需要一个外部类的实例为基础,可以直接实例化
语法:new 外部类.静态内部类();
因为没有一个外部类的实例,所以在静态内部类里面不可以访问外部类的实例属性和方法
除了可以访问外部类的私有静态成员外,静态内部类和普通类没什么大的区别
package charactor; public class Hero { public String name; protected float hp; private static void battleWin(){ System.out.println("battle win"); } //敌方的水晶 static class EnemyCrystal{ int hp=5000; //如果水晶的血量为0,则宣布胜利 public void checkIfVictory(){ if(hp==0){ Hero.battleWin(); //静态内部类不能直接访问外部类的对象属性 System.out.println(name + " win this game"); } } } public static void main(String[] args) { //实例化静态内部类 Hero.EnemyCrystal crystal = new Hero.EnemyCrystal(); crystal.checkIfVictory(); } }
匿名类指的是在声明一个类的同时实例化它,使代码更加简洁精练
通常情况下,要使用一个接口或者抽象类,都必须创建一个子类

有的时候,为了快速使用,直接实例化一个抽象类,并“当场”实现其抽象方法。
既然实现了抽象方法,那么就是一个新的类,只是这个类,没有命名。
这样的类,叫做匿名类
匿名类
package charactor; public abstract class Hero { String name; //姓名 float hp; //血量 float armor; //护甲 int moveSpeed; //移动速度 public abstract void attack(); public static void main(String[] args) { ADHero adh=new ADHero(); //通过打印adh,可以看到adh这个对象属于ADHero类 adh.attack(); System.out.println(adh); Hero h = new Hero(){ //当场实现attack方法 public void attack() { System.out.println("新的进攻手段"); } }; h.attack(); //通过打印h,可以看到h这个对象属于Hero$1这么一个系统自动分配的类名 System.out.println(h); } }
本地类可以理解为有名字的匿名类
内部类与匿名类不一样的是,内部类必须声明在成员的位置,即与属性和方法平等的位置。
本地类和匿名类一样,直接声明在代码块里面,可以是主方法,for循环里等等地方
package charactor; public abstract class Hero { String name; //姓名 float hp; //血量 float armor; //护甲 int moveSpeed; //移动速度 public abstract void attack(); public static void main(String[] args) { //与匿名类的区别在于,本地类有了自定义的类名 class SomeHero extends Hero{ public void attack() { System.out.println( name+ " 新的进攻手段"); } } SomeHero h =new SomeHero(); h.name ="地卜师"; h.attack(); } }
步骤 5 :

在匿名类中使用外部的局部变量

edit edit
在匿名类中使用外部的局部变量,外部的局部变量必须修饰为final

为什么要声明为final,其机制比较复杂,请参考第二个Hero代码中的解释

注:在jdk8中,已经不需要强制修饰成final了,如果没有写final,不会报错,因为编译器偷偷的帮你加上了看不见的final
package charactor; public abstract class Hero { public abstract void attack(); public static void main(String[] args) { //在匿名类中使用外部的局部变量,外部的局部变量必须修饰为final final int damage = 5; Hero h = new Hero(){ public void attack() { System.out.printf("新的进攻手段,造成%d点伤害",damage ); } }; } }
package charactor; public abstract class Hero { public abstract void attack(); public static void main(String[] args) { //在匿名类中使用外部的局部变量damage 必须修饰为final int damage = 5; //这里使用本地类AnonymousHero来模拟匿名类的隐藏属性机制 //事实上的匿名类,会在匿名类里声明一个damage属性,并且使用构造方法初始化该属性的值 //在attack中使用的damage,真正使用的是这个内部damage,而非外部damage //假设外部属性不需要声明为final //那么在attack中修改damage的值,就会被暗示为修改了外部变量damage的值 //但是他们俩是不同的变量,是不可能修改外部变量damage的 //所以为了避免产生误导,外部的damage必须声明为final,"看上去"就不能修改了 class AnonymousHero extends Hero{ int damage; public AnonymousHero(int damage){ this.damage = damage; } public void attack() { damage = 10; System.out.printf("新的进攻手段,造成%d点伤害",this.damage ); } } Hero h = new AnonymousHero(damage); } }
步骤 6 :

练习-内部类

练习难度 edit edit Or  姿势不对,事倍功半! 点击查看做练习的正确姿势
创建一个Item的匿名类

Item有抽象方法disposable(), 就像抽象类练习 中要求的那样。
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
查看本答案会花费2个积分,您目前总共有点积分。查看相同答案不会花费额外积分。 积分增加办法 或者一次性购买JAVA 基础总计0个答案 (总共需要0积分)
查看本答案会花费2个积分,您目前总共有点积分。查看相同答案不会花费额外积分。 积分增加办法 或者一次性购买JAVA 基础总计0个答案 (总共需要0积分)
账号未激活 账号未激活,功能受限。 请点击激活


HOW2J公众号,关注后实时获知最新的教程和优惠活动,谢谢。


提问已经提交成功,正在审核。 请于 我的提问 处查看提问记录,谢谢
关于 JAVA 基础-接口与继承-内部类 的提问

尽量提供截图代码异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 982790551
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
在已经存在的几千个提问里,有相当大的比例,是因为使用了和站长不同版本的开发环境导致的,比如 jdk, eclpise, idea, mysql,tomcat 等等软件的版本不一致。
请使用和站长一样的版本,可以节约自己大量的学习时间。 站长把教学中用的软件版本整理了,都统一放在了这里, 方便大家下载: https://how2j.cn/k/helloworld/helloworld-version/1718.html

上传截图