跟我一起学JAVAEE吧——JAVA_SE篇——day09上课笔记(详解final修饰符的作用,内部类,成员内部类,局部内部类,匿名内部类傻傻分不清?)

day 09

final修饰符

  • 作用

    • 修饰局部变量

      • 一旦final修饰,局部变量不可变
      • 用final修饰的变量,只能被赋值一次
    • 修饰成员变量

      • 用final修饰同样不可变
      • 由于成员变量有默认值,所以使用final修饰后必须手动赋值,不会再有默认值
      • 对于final修饰的成员变量,要么手动赋值,要么构造方法赋值,选其一
      • 如果使用构造方法赋值,必须保证每个构造方法都要对其进行赋值
    • 修饰方法

      • 当final修饰一个方法的时候,这是一个最终方法,也就是不能被重写
      • 对于类和方法来说。abstract和final不能同时使用,因为矛盾
    • 修饰类

      • final修饰引用数据类型地址值不可变
      • 对于类和方法来说,abstract和final不能同时修饰,因为矛盾
      • final修饰一个类,这个类不能被继承,所以其中方法也不能被重写
    • 修饰对象

      • final修饰引用数据类型,引用数据类型地址不可变

        	final Student s1=new Student("张三"20);
            s1=new Stuent ("李四"30)//报错,地址不可变
        
  • 修饰符 同类中 同一包中 不同包子类 不同包非子类
    public Y Y Y Y
    protected Y Y Y F
    default(不写) Y Y F F
    private Y F F F

内部类

  • 内部类:一个类定义另一个类

    • 使用方法:
    	外部类名称. 内部类名称 对象名 = new 外部类名称().内部类名称()
    
    • 内部类访问外部类可以随便访问

    • 外部类访问内部类需要内部类对象

    • 成员内部类

      • 直接是类的成员
      public class Demo02InnerClass {
          private String name="外部类名";
          public class Heart{//定义一个内部类Heart
              private String name="内部类名";//内部类的成员变量
      
              public void  beat(){内部类的成员方法
                  System.out.println("我是内部类方法");
                  System.out.println(name);//打印内部类的成员变量
              }
          }
          public void methodBody(){
              System.out.println("我是外部类方法");
              System.out.println(new Heart().name);//内部类的匿名对象调用成员变量
              new Heart().beat();//内部类的匿名对象调用成员方法
          }
      	}
      
      public class Demo03TestClass {
          public static void main(String[] args) {
              Demo02InnerClass obj=new Demo02InnerClass();
              obj.methodBody();
          }
      }
      

      我是外部类方法
      内部类名
      我是内部类方法
      内部类名

    • 局部内部类

      • 如果一个类定义在一个方法内部,那么这个就是一个局部内部类,“局部”只有当前方法可以使用它,出了这个方法就不能使用

      • 外部类:public / default

      • 成员内部类:public /protocted /default /private

      • 局部内部类:什么都不写

        	public class Demo03Out {
           		public void method(){//成员方法
              	 	int i=10;//局部变量
               		class Inner{//方法中定义的内部类,局部内部类
                  		int i=20;//内部类的变量
                   		public void methodInner(){//内部类的方法
                     		  System.out.println(i);//打印内部类的变量
                  		 }
              	 }
              		 Inner inner=new Inner();//声明内部类对象
              		 inner.methodInner();//调用内部类方法
          		 }
        	}
        
        
        public class Demo03TestClass {
            public static void main(String[] args) {
                Demo03Out obj=new Demo03Out ();//声明外部类对象
                obj.method;//调用外部类的方法
            }
        

        20

    • 匿名内部类

      • 作用:如果接口的实现类只需要使用唯一的一次,那么这种情况可以省略该类定义直接改为匿名内部类

      • 格式:

        	new 接口名称(){
                //覆盖重写的方法
        	}
        
      • new 接口名称 用来创建对象的动作

      • 接口名称就是匿名内部类需要实现的接口

      • {。。。}就是覆盖重写的方法

      • 注意

        • 匿名内部类,在创建对象的时候,只能使用唯一的一次
        • 匿名对象在直接调用方法的时候只能使用一次,如果希望一个对象调用多次方法,那么就需要声明一个对象
        • 匿名内部类是省略了实现类,匿名对象是省略了对象名
        • 匿名内部类和匿名对象不是一个东西
      • 代码举例 以游戏人物技能为例

        	//定义一个技能接口
        	public interface Skill {
            public void use();//使用技能的抽象方法
        	}
        
        	//写一个英雄的类
        	public class Hero {
            	private String name;//成员变量存取方法名
            	private Skill skill;//定义一个Skill类型的引用变量存取对象
            	public void attack(){//英雄攻击的方法
                	System.out.println(name+"释放了技能");
               		skill.use();//调用重写use方法
                	System.out.println(name+"技能释放完成");
            	}
            	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) {//setSkill方法传递对象地址
                	this.skill = skill;
            	}
            }
        
        	//写一个实现类实现接口
        	public class SkillImplement implements Skill {//实现Skill接口
            	@Override
            	public void use() {//重写接口中的方法
                	System.out.println("哈萨克");//实现内容
            	}
        	}
        
        //定义一个测试类
        public class HeroTest {
        
            public static void main(String[] args) {
                Hero hero=new Hero();//声明一个Hero的对象
                hero.setName("亚索");//设置影响名字
                hero.setSkill(new SkillImplement());//利用匿名对象,把实现类的对象传递给Hero对象里面的kill
                hero.attack();//调用方法攻击
            }
        }
        

        亚索释放了技能
        哈萨克
        亚索技能释放完成

        这并不是匿名内部类的使用,只是匿名对象传递参数实现功能

        下面才是匿名内部类的使用

        public class HeroTest {
        
            public static void main(String[] args) {
                Hero hero=new Hero();
                hero.setName("亚索");
                hero.setSkill(new SkillImplement());
                hero.attack();
                
                Hero hero1=new Hero();//声明一个Hero的对象用hero1指向
                hero1.setName("李青");//设置英雄名字为李青
                hero1.setSkill(new Skill() {//在参数栏里直接使用匿名内部类传递参数
                    @Override
                    public void use() {//直接重写use方法
                        System.out.println("一库");//具体实现的功能
                    }
                });
                hero1.attack();//英雄发动攻击
        
            }
        }
        

        亚索释放了技能
        哈萨克
        亚索技能释放完成

        李青释放了技能
        一库
        李青技能释放完成

        大家是不是发现神奇的地方,我没有写实现类重写方法就实现了抽象类use()。其实并不是,我们直接在参数栏里重写实现了,相当于匿名了实现类。

        这样的好处就是可以不用写实现类,那我们是不是以后就不用写实现类了,并不。如果需要多次使用到实现类,就定义实现类,如果很少或只用一次实现类,就可以利用匿名内部类来省去创建一次实现类的麻烦,当然,究竟怎么用,偏好于自己喜好。

猜你喜欢

转载自blog.csdn.net/weixin_44115522/article/details/107542256