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()。其实并不是,我们直接在参数栏里重写实现了,相当于匿名了实现类。
这样的好处就是可以不用写实现类,那我们是不是以后就不用写实现类了,并不。如果需要多次使用到实现类,就定义实现类,如果很少或只用一次实现类,就可以利用匿名内部类来省去创建一次实现类的麻烦,当然,究竟怎么用,偏好于自己喜好。
-