内部类
如果一个事物的内部包含另一个事物,那么这就是一个类内部包含另一个类
分类:
1.成员内部类
2.局部内部类(包含匿名内部类)
成员内部类
定义格式:
修饰符 class 外部类名称{
修饰符 class 内部类名称{
}
}
注意:内用外随意,外用内,需要内部类对象
public class Body{//外部类
public class Heart{//成员内部类
}
}
如何使用成员内部类
1.间接方式:在外部类的方法当中,使用内部类,然后main只是调用外部类的方法。
2.直接方式:外部类名称 对象名 =new 外部类名称().new 内部类名称();
内部类的重名变量访问
public class Outer{
int num=10;//外部类的成员变量
public class Inner{
int num=20;//内部类的成员变量
public void methodInner(){
int num=10;//内部方法的局部变量
System.out.println(num);//局部变量,就近原则
System.out.println(this.num);//毫无疑问是自己类的成员变量
System.out.println(Out.this.num);//这么访问外部类的成员变量
}
}
}
局部内部类
类如果一个类定义在一个方法的内部,那么这就是一个局部内部类。
就是只有在当前所属的方法才能使用它,出了这个方法的外面就不能用了。
格式:
修饰符 class 外部类名称{
修饰符 返回值类型 外部类方法名称(参数列表){
class 局部内部类名称{
}
}
}
public class Outer{
public void methodOuter(){
class Inner{//局部内部类
int num=10;
public void methodInner(){
System.out.println("num");//10
}
}
Inner inner =new Inner();//只有在methodOuter方法内才能使用
inner.methodInner();
}
}
public class Demo{
public static void main(String [] args){
Outer obj =new Outer();
obj.methodOuter();
}
}
局部内部类的final问题
局部内部类,如果希望访问所在方法的局部变量,那么这个局部变量必须是有效final的(可以是final修饰的,也可以是其他修饰但确实没有改变的)
public class MyOuter{
public void methodOuter(){
int num=10;//虽然为int,但确实没有改变,可以
//final int num=10;也可以直接给这样写
class MyInner{
public void methodInner(){
System.out.println(num);
}
}
}
}
简述为什么保持不变的原因:
new出来的对象在堆内存中,局部变量是跟着方法走的,在栈内存当中,方法运行结束后,立刻出栈,局部变量跟着立刻消失,但是new出来的对象会在堆中持续存在,如果保证局部变量不变,局部内部类就可以复制一份局部变量跟随局部内部类对象,即使局部变量消失了,也能访问。
小节权限修饰符
public > protected > (default) > private
定义一个类时,权限修饰符规则:
1.外部类:public /(default)
2.成员内部类:public /protected/(default)/private
3.局部内部类:什么都不能写
匿名内部类
如果接口的实现类(或者是父类的子类)只需要使用唯一的一次,那么这种情况下就可以省略掉该类的定义,使用匿名内部类。
定义格式:
接口名称 对象名 =new 接口名称(){
//覆盖重写所有抽象方法
};
//正常情况下
package text;
public interface MyInterface {
void method();
}
package text;
public class MyInterfaceImpl implements MyInterface{
@Override
public void method() {
System.out.println("实现类覆盖重写了方法!");
}
}
package text;
public class Demo {
public static void main(String[] args) {
MyInterface impl =new MyInterfaceImpl();
impl.method();
}
}
//但是上述实现类只用了一次,可以考虑使用匿名内部类
package text;
public interface MyInterface {
void method();
}
package text;
public class Demo {
public static void main(String[] args) {
MyInterface obj = new MyInterface() {//这个大括号包住的算是没有名字的类,这就叫做匿名内部类
@Override
public void method() {
System.out.println("匿名内部类实现了方法!");
}
};
obj.method();
}
}
对格式"new 接口名称(){...}"进行解析:
1.new代表创建对象的动作
2.接口名称就是匿名内部类需要实现哪个接口
3.{...}这才是匿名内部类的内容
另外注意:
1.匿名内部类,在创建对象的时候,只能使用唯一的一次,如果希望使用多次,而且内容一样的话要么就写实现类,要么就重复写多次匿名内部类。
2.匿名对象,在调用方法时,只能调用唯一一次,如果希望同一个对象调用多次方法,那么必须给对象起个名字。
//综合匿名类和匿名对象
package text;
public interface MyInterface {
void method1();
void method2();
}
package text;
public class Demo {
public static void main(String[] args) {
new MyInterface(){
@Override
public void method1() {
}
@Override
public void method2() {
}
}.method1();//只有new,没有对象,new完直接调用方法,既使用了匿名类也使用了匿名对象
}
}
3.匿名内部类是省略了实现类或子类名称,但是匿名对象是省略了对象名称。
它俩不是一回事!!!
类作为成员变量
传的时候先new一个就行,其实String类型也是一个类,但是它不用new。
package Demo01;
public class Weapon {
private String code;//武器的代号
public Weapon(){
}
public Weapon(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
package Demo01;
public class Hero {
private String name;//英雄名字
private Weapon weapon;//英雄武器
private int age;//
public Hero() {
}
public Hero(String name, Weapon weapon, int age) {
this.name = name;
this.weapon = weapon;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Weapon getWeapon() {
return weapon;
}
public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package Demo01;
public class Demo {
public static void main(String[] args) {
Hero hero =new Hero ();
hero.setAge(20);
hero.setName("德玛");
Weapon weapon =new Weapon();
weapon.setCode("无尽之刃");
hero.setWeapon(weapon);
System.out.println("一个"+hero.getAge()+ "岁的"+hero.getName()+"拿着"+weapon.getCode()+"击杀了敌方!");
}
}
接口作为成员变量和成员方法
//公共
package Demo02;
public class Hero {
private String name;
private Skill skill;
public void attack(){
System.out.println("我叫"+name+",我放技能:");
skill.use();
System.out.println("技能施放结束!");
}
public Hero() {
}
public Hero(String name, Skill skill) {
this.name = name;
this.skill = skill;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Skill getSkill() {
return skill;
}
public void setSkill(Skill skill) {
this.skill = skill;
}
}
package Demo02;
public interface Skill {
void use();//施放技能的抽象方法
}
//方法一:正常实现类调用
package Demo02;
public class SkillImpl implements Skill{
@Override
public void use() {
System.out.println("qqq");
}
}
package Demo02;
public class Demo {
public static void main(String[] args) {
Hero hero =new Hero();
hero.setName("锐雯");//设置英雄名称
hero.setSkill(new SkillImpl());
hero.attack();
}
}
//方法二:使用匿名内部类
package Demo02;
public class Demo {
public static void main(String[] args) {
Hero hero =new Hero();
Skill skill=new Skill() {
@Override
public void use() {
System.out.println("qqq");
}
};
hero.setSkill(skill);
hero.attack();
}
}
//方法三:再简单一点,同时使用匿名内部类和匿名对象
package Demo02;
public class Demo {
public static void main(String[] args) {
Hero hero =new Hero();
hero.setName("锐雯");//设置英雄名称
hero.setSkill(new Skill(){
@Override
public void use() {
System.out.println("qqq");
}
});
hero.attack();
}
}
接口作为方法的参数
java.util.List正是ArrayList所实现的接口
import java.util.ArrayList;
import java.util.List;
public class Demo{
public static void main(String[] args) {
//左边是接口名称,右边是实现类名称,就是多态写法
List<String> list =new ArrayList<>();
}
public static List<String> addNames(List<String> list){
list.add("111");
return list;
}
}
Comments NOTHING