java基础——day09-1 final、权限、内部类、引用类型
final关键字
概述:
final:不可以改变。用于修饰类、方法、变量(成员变量、局部变量)
特点:
1.类:被修饰的类,不能被继承
2.方法:被修饰的方法,不能被重写
3.变量:被修饰的变量,不能重新赋值
使用方式:
1.修饰类(不能被继承)
含义:当前类不能有任何子类,但是一定有父类(所有类 默认的父类是Object)
格式:public final class 类名{}
package day10.day10_1; //final关键字 修饰类 public final class Myclass { //里面的变量和方法 该怎么写就怎么写 int number = 10; public void method(){ System.out.println("this is final class"); } }
用途:String类、Math类、Scanner类等,都是被final修饰的,目的在于供我们使用,而不让我们改变内容。
注意:一个类,如果被final修饰,那么其中的所有的成员方法都无法覆盖重写
2.修饰方法(不能被重写)
含义:当一个final修饰一个方法,那么这个方法是最终方法,不能被覆盖重写。
格式:修饰符 final 返回值类型 方法名(参数列表) {}
package day10.day10_1.day10_2; public class Fu { public void method(){ System.out.println("父类方法执行"); }; //定义final修饰的方法 public final void methodA(){ System.out.println("被final修饰的父类方法"); } }
package day10.day10_1.day10_2; public class Zi extends Fu { @Override public void method() { //覆盖重写父类method方法 System.out.println("父类方法重写"); } // public void methodA(){ // System.out.println("错误写法"); // } }
package day10.day10_1.day10_2; public class demo { public static void main(String[] args) { Zi son = new Zi(); son.method(); //子类任然可以调用父类final修饰的成员方法 son.methodA(); } }
注意:
1.final修饰的父类成员方法,虽不能被重写,但是子类对象还是可以调用,因为子类对象没有,会向上找。
2.对于类、方法来说,abstract和final关键字不能同时使用,因为矛盾。(abstract一定要覆盖重写 final一定不能覆盖重写)
3.修饰变量(不能被重新赋值)
1、局部变量——基本类型
基本类型的局部变量,被final修饰后,只能赋值一次,不能再更改,例如:
package day10.day10_1.day10_2; public class demo01 { public static void main(String[] args) { final int num; //声明变量 final修饰 num = 10; //第一次赋值 //num = 20; //第二次赋值 报错 } }
提问:那么如何通过编译?
package day10.day10_1.day10_2; public class demo01 { public static void main(String[] args) { for (int i = 0; i < 5; i++) { final int num = i; System.out.println(num); } } }
2、局部变量——引用类型
引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能再更改。但是不影响对象内部成员变量值的修改。
package day10.day10_1.day10_3; public class User { private String name; //构造方法 public User() {} public User(String name) { this.name = name; } //get & set public String getName() { return name; } public void setName(String name) { this.name = name; } //成员方法 }
package day10.day10_1.day10_3; public class demo { public static void main(String[] args) { //创建User对象 User user = new User("赵丽颖"); System.out.println(user.getName());//赵丽颖 System.out.println(user); //User@452b3a41 //改变的是其地址值 user = new User("冯绍峰"); System.out.println(user.getName());//冯绍峰 System.out.println(user); //User@4a574795 System.out.println("==================="); final User user1 = new User("刘亦菲"); System.out.println(user1); // user1 = new User("胡歌"); 错误写法 fianl变量引用类型 不可改变 user1.setName("胡歌"); System.out.println(user1); System.out.println(user1.getName()); //胡歌 地址值一样 } }
3、成员变量
1.成员变量涉及到初始化问题,初始化方式有两种,二选一
2.成员变量具有默认值,所以用了final后,必须手动赋值。
a、显示初始化(直接赋值)

b、构造方法初始化(构造方法里赋值)

权限修饰符
概述
Java中提供了四种访问权限,使用不同访问权限修饰符,被修饰的内容会有不同的访问权限
1.public:公共的
2.protected:受保护的
3.default:默认的
4.private:私有的
不同权限的访问能力

public具有最大权限,private最小访问权限。
使用权限建议:
1.成员变量使用private,隐藏细节
2.构造方法使用public,方便创建对象
3.成员方法使用public,方便调用方法
内部类
概述
1.什么是内部类
将一个类A 定义在 另一个类B中,则类A称为内部类,B则称为外部类
例如:身体和心脏的关系,汽车和发动机引擎的关系
成员内部类与局部内部类
1.成员内部类
定义格式:

注意:内用外,随意访问;外用内,需要借助内部类对象。
package day10.day10_1.day10_5; public class body { //外部类 public class heart{ //定义成员内部类 //内部类的成员方法 public void methodHeart(){ System.out.println("心脏跳动"); System.out.println("我叫"+name); //可以访问 正确写法 } } //外部类的成员变量 private String name; //外部类的成员方法 public void methodBody(){ System.out.println("外部类方法"); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
如何使用内部类:
1.间接使用:在外部内的方法中,使用内部类,然后main方法只是调用外部类的方法
package day10.day10_1.day10_5; public class body { //外部类 public class heart{ //定义成员内部类 //内部类的成员方法 public void methodHeart(){ System.out.println("心脏跳动"); System.out.println("我叫"+name); //可以访问 正确写法 } } //外部类的成员变量 private String name; //外部类的成员方法 public void methodBody(){ System.out.println("外部类方法"); //间接使用 heart xinzang = new heart(); xinzang.methodHeart(); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
package day10.day10_1.day10_5; import day10.day10_1.day10_4.Person; public class demo { public static void main(String[] args) { body Person = new body(); Person.setName("张一山"); //外部类的set方法 //接见使用内部类 Person.methodBody(); } }
2.直接使用:
外部类名称.内部类名称 对象名 = new 外部类名称().new内部类名称();
package day10.day10_1.day10_5; public class body { //外部类 public class heart{ //定义成员内部类 //内部类的成员方法 public void methodHeart(){ System.out.println("心脏跳动"); System.out.println("我叫"+name); //可以访问 正确写法 } } //外部类的成员变量 private String name; //外部类的成员方法 public void methodBody(){ System.out.println("外部类方法"); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
package day10.day10_1.day10_5; import day10.day10_1.day10_4.Person; public class demo { public static void main(String[] args) { //直接使用 body.heart person = new body().new heart(); // person.setName = "错误写法" 内部类没法调用外部类的成员方法 person.methodHeart(); } }
注意:使用内部类new出来的对象 没办法访问外部类的成员方法。
3.内部类成员变量同名问题
package day10.day10_1.day10_5; public class Outer {//外部类 int num = 10; //外部类成员变量 public class Inner{//内部类 int num = 20; public void method(){//内部类的成员方法 int num = 30; System.out.println(num); //就近原则 输出30 System.out.println(this.num); //内部类的成员变量 20 // System.out.println(super.num); 错误写法 因为内部类不是外部类 心脏不是身体 System.out.println(Outer.this.num);//外部的成员变量 10 } } }
package day10.day10_1.day10_5; public class demo01 { public static void main(String[] args) { //创建直接访问内部类的对象 Outer.Inner Test = new Outer().new Inner(); Test.method(); } }
在 内部类中 访问 外部类 的成员变量,使用:外部类.this.成员变量名
2.局部内部类(包含匿名内部类)
定义:如果一个类 定义在一个 方法内部,那么它就是一个局部类。
格式:
修饰符 class 外部类名称{
修饰符 返回值类型 方法名称(参数列表){
修饰符 class 局部内名称
}
}
例如:需要简介访问
package day10.day10_1; public class outer {//外部类 //外部成员方法 public void methodOuter(){ class Inner{//局部内部类 int num = 10; public void methodInner(){ System.out.println(num); //10 } } //间接使用 Inner inner = new Inner(); inner.methodInner(); } }
package day10.day10_1; public class demo { public static void main(String[] args) { //创建外部类对象 outer duixiang = new outer(); duixiang.methodOuter(); } }
使用权限建议:
1.外部类:public / default
2.内部类:public / protected / default / private
3.局部内部类:什么修饰符都不写
3.匿名内部类(最重要)
如果接口的实现类(父类的子类)只需要使用唯一的一次[就new 的那一次]
那么这种情况下可以省略掉类的定义,而改为【匿名内部类】
定义格式:
接口名称 对象名 = new 接口名称(){
//覆盖重写接口中的所有抽象方法 };
例如:
package day10.day10_1; public interface MyInterface { void method(); }
package day10.day10_1; import day09.day08_1.day08_2.Myinterface; public class demo { public static void main(String[] args) { //匿名局部内部类 Myinterface duixiang = new Myinterface() { @Override public void method() { System.out.println("匿名内部类 实现了方法"); } }; //调用匿名内部类 duixiang.method(); } }
注意事项:
1、对 “new 接口名称(){....}” 的解释
1.new 代表创建对象
2.接口名称:就是匿名内部类需要实现哪个接口
3.{...}:匿名内部类的内容
2、匿名内部类使用注意事项
1.匿名内部类,在创建对象时,只能使用唯一 一次。用一次 new接口名称{} 一次
如果希望多次创建对象,而且类的内容一样,就必须使用实现类。
2.匿名对象
匿名内部类:Interface obj = new Interface{...};
obj.匿名方法
匿名对象:new interface{....}.匿名方法;
所以匿名对象 只能调用一次匿名方法 再次使用 需要重写new
3.匿名内部类时省略了实现类(子类),匿名对象省略了对象名称。
引用类型用法总结
概述:
实际开发中,引用类型的使用十分重要,也十分普遍。
基本类型可以作为成员变量,作为方法的参数,那么引用类型也是可以的。
class作为成员变量
例如:将英雄单独为一类,其包含英雄的基本属性,再单独定义一个武器类,武器类作为成员变量提供给英雄使用
package day11; //定义英雄类 public class Hero { private String name;//定义英雄名字 private int age;//定义英雌年龄 private weapons weapon;//使用武器类作为成员变量 //成员方法 public void attack(){ //class作为成员变量 在调用的时候 还是需要使用get方法 System.out.println(age+"岁的英雄"+name+",正使用"+weapon.getWeaponName()+"攻击敌人!"); } //构造方法 public Hero() { } public Hero(String name, int age, weapons weapon) { this.name = name; this.age = age; this.weapon = weapon; } //get & set 方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public weapons getWeapon() { return weapon; } public void setWeapon(weapons weapon) { this.weapon = weapon; } }
package day11; //定义英雄武器类 public class weapons { private String weaponName; public weapons(){} public weapons(String weaponName) { this.weaponName = weaponName; } public String getWeaponName() { return weaponName; } public void setWeaponName(String weaponName) { this.weaponName = weaponName; } }
package day11; public class demo { public static void main(String[] args) { //创建 hero对象 Hero hero = new Hero(); //设置英雄的姓名和年龄 hero.setName("马冬梅"); hero.setAge(18); //创建英雄武器 weapons tools = new weapons(); tools.setWeaponName("拖鞋"); hero.setWeapon(tools); hero.attack(); } }
类作为成员变量时,对他进行赋值操作,实际上是赋值给 该类的一个对象。
Interface作为成员变量
接口是对方法的封装,对应游戏当中,可以看做角色的扩展技能。
例如:
package day11.day11_1; public interface Skill { public abstract void use();//释放技能的抽象方法 }
package day11.day11_1; public class Hero { //成员变量 private String name; private Skill skill; //构造方法 public Hero() {} public Hero(String name, Skill skill) { this.name = name; this.skill = skill; } //成员方法 public void attacked(){ System.out.print(name+"正在释放技能:"); skill.use(); System.out.print(",攻击敌人"); } //get & set 方法 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 day11.day11_1; public class Game { public static void main(String[] args) { Hero hero = new Hero(); hero.setName("艾希"); //设置英雄 可以使用实现类 也可以使用匿名内部类 Skill skill = new Skill() { @Override public void use() { System.out.print("穿云箭"); } }; hero.setSkill(skill); hero.attacked(); System.out.println("\n=============================="); //使用匿名内部类和匿名对象 hero.setSkill(new Skill() { @Override public void use() { System.out.print("急速攻击"); } }); hero.attacked(); } }
设计接口作为成员变量,增强了程序的灵活性和可扩展性。
接口作为成员变量时,对它进行赋值的操作,实质上是赋给它 该类接口的 一个子类对象
Interface作为方法参数和返回值类型
java.util.list正是ArrayList所实现的接口。
package day11.day11_2; import java.util.ArrayList; import java.util.List; public interface Myinterface { public static List<Integer> getEvenNum(List<Integer> list){ //创建保存偶数的集合 ArrayList<Integer> evenList = new ArrayList<>(); //变量list 判断偶数元素 并添加到evenList中 for (int i = 0; i < list.size(); i++) { if(list.get(i) % 2 ==0){ evenList.add(list.get(i)); } } return evenList; } }
package day11.day11_2; import java.util.ArrayList; import java.util.List; public class demo { public static void main(String[] args) { ArrayList<Integer> number = new ArrayList<>(); for (int i = 0; i < 10; i++) { number.add(i); } List<Integer>list = Myinterface.getEvenNum(number); System.out.println(list); } }
接口作为参数时,传递的是它的子类对象
接口作为返回值类型时,返回它的子类对象

浙公网安备 33010602011771号