(final、权限、内部类、引用类型)

版权声明:Java基础,个人笔记。 https://blog.csdn.net/liu19951104/article/details/81556649

1.final关键字

final:不可改变你,可以用于修饰类、方法和变量(final用于修饰不可改变的内容)

  • 类:被修饰的类,不能被继承
  • 方法:被修饰打的方法不能被重写
  • 变量:被修饰的变量,不能被重新赋值

使用方式:

修饰类(格式):

final  class 类名{
}

修饰方法(格式):

修饰符 final 返回值类型 方法名 (参数列表){
        //方法体
} //重写被final修饰的方法,编译时就会报错

修饰变量

1.局部变量---基本类型

public static Demo01{
    public static void main(){
        //声明变量,使用final修饰
        final int a;
        //第一次赋值
        a = 10;
        //第二次赋值
        a = 20; //报错,不可重新赋值

        //声明变量,直接赋值,使用final修饰
        final int b = 10;
        //第二次赋值
        b = 20; // 报错,不可重新赋值          
    }
}

我们可以考虑下面这种情况:

//写法一
final int c = 0;
for(int i = 0; i < 10; i++){
    c=i;
    System.out.println(c);
}

//写法二
for(int i = 0;i < 10; I++){
    final int c = i;
    System.out.println(c);

}
// 根据final的定义,写法1报错!写法2能通过编译的原因是:每次循环,都是一个新的变量c

2.局部变量---引用类型

引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能再改。但是不影响对象内部的成员变量值的修改,代码如下:

public class Demo02{
    public static void main (String[] args){
        //创建User对象
        final User u = new User();
        //创建 另一个 User对象
        u = new User(); //报错,指向了新的对象,地址值改变 
        
        //调用setName方法
        u.setName("张三"); //可以修改
    }
}

3.成员变量

成员变量涉及到初始化的问题,初始化方式有两种,只能二选一

  • 显示初始化
public class User{
    final String USERNAME = "张三";
    private int age;
}
  • 构造方法初始化
public class User {
    final String USERNAME;
    private int age;
    pubic User(String name, int age){
        this.USERNAME = username;
        this.age = age;
    }
}

在这里我们要注意:被final修饰的常量名称,所有字母都要大写;

2.权限修饰符

java中一般提供四类访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限

  • public:公共的
  • protected:受保护的
  • default:默认的
  • private:私有的
  public protected default(空的) private

同一类中

同一包中(子类与无关类)  
不同包的子类    
不同包中的无关类      

从上表可以看出。public具有最大的访问权限,private则是最小权限

在编写代码的时候。如果没有特殊的考虑,一般建议这样使用权限:

  • 成员变量使用private,隐藏细节
  • 构造方法使用public,方便创建对象
  • 成员方法使用public,方便调用方法不加权限修饰符,其访问能力与default修饰符相同

3.内部类

将一个类A定义在另一个类B的中,里面的那个类A就称为内部类,B则成为外部类

成员内部类:定义在类中方法外的类,格式为:

class 外部类{
    class 内部类{

    }
}

如果我们在描述一个事物的时候,这个事物还包含了其他事物,我们就可以使用内部类这种结构

代码举例:

class Car{ //外部类
    class Engine{ //内部类
    }
}

访问特点:

  • 内部类可以直接访问外部类的成员,包括私有成员
  • 外部类要访问内部类的成员,必须要创建内部类的对象

创建内部类对象的格式:

外部类名.内部类名 对象名 = new 外部类型().new 内部类型();

演示代码如下:

//定义类
public class Person {
    private boolean live = true ;
    class Heart {
        public void jump(){
            //直接访问外部类成员
            if(live){
                 System.out.println("心脏在跳动");   
            }else {
                 System.out.println("心脏不跳了");
            }
        }
    }
    public boolean islive(){
         return live;   
    }
    public void setLive(boolean live){
        this.live = live;
    }
}

//定义测试类
public class InnerDemo{
    public static void main(String[] args){
        //创建外部类对象
        Person p = new Person();
        //创建内部类对象
        Heart heart = new Heart();

        //调用内部类方法
        heart.jump(); //心脏在跳动
        //调用外部类对象
        p.setLive(false);
        //调用内部类方法
        heart.jump(); //心脏不跳了            
    }
}

内部类仍然是一个独立的类,在编译后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号,例如:     Person$Heart.class

匿名内部类【重点】

匿名内部类:是内部类的简化写法,其本质为一个[带具体实现的][父类或者父类接口的][匿名的]子类对象

前提:匿名内部类必须继承一个父类或者实现一个接口

new 父类名或者接口名(){
    //方法重写
    @Override
    public void method(){
        //执行语句
    }
};

使用方式,以接口为例:

//定义接口
public abstract class FlyAble{
    public abstract void fly();
}
//创建匿名内部类,并调用:
public class InnerDemo{
    public static void main(String[] args){
        /*
        1.等号右边:是匿名内部类,定义并创建该接口的子类对象
        2.等号左边:是多态赋值,接口类型引用指向子类对象
        */
        FlyAble f = new FlyAble(){
            public void fly(){
                System.out.println("我飞了~~~");
        }
    };
    //调用fly方法,执行重写后的方法
    f.fly();          
    }
}

    //通常在方法的形式参数是接口或者抽象类时,也可以将匿名内部了作为参数传递,代码如下       
    public static void main(){
    /*
    1.等号右边:定义并创建该接口的子类对象
    2.等号左边:是多态,接口类型引用指向子类对象
    */
    FlyAble f = new FlyAble(){
        public void fly(){
             System.out.println("我飞了~~~");
        }
    };
    //将f传递给showFly方中
    showFly(f);
    }
    public static void showFly(FlyAble f){
        f.fly();
    }
//以上两步也可以简化为一步,代码如下:
public class InnerDemo03{
    public static void main(String[] args){
        /*
        创建匿名内部类,直接传递给showFly(FlyAble f)
        */
        showFly(new FlyAble)(){
            public void fly(){
                System.out.println("我飞了~~~");
            }
        });
    }

    public static void showFly(FlyAble f){
        f.fly();
    }
}

引用类型用法总结

class作为成员变量

在定义一个类Role(游戏角色)时,代码如下:

class Role{
    int id;
    int blood;
    String name;
}
//定义武器类
class Weapon{
    String name; // 武器名称
    int hurt; //伤害值
}
//定义穿盔甲类
class Armour{
    String name;// 装备名称
    int protect;//防御值
}
//定义角色类
class Role{
    int id;
    int blood;
    String name;
    //添加武器属性
    Weapon wp;
    //添加盔甲属性
    Armour ar;
    
    // 提供get/set方法
    public Weapon getWp(){
        return wp;
    }
    public void setWeapon(Weapon wp){
        this.wp = wp;
    }
    public Armour getArmour(){
        return ar;
    }
    //攻击方法
    public void attack(){
        System.out.println("使用"+ wp.getName()+",造成"+wp.getHurt()+"点伤害");
    }

    //穿戴盔甲
    public void wear(){
        this.blood += ar.getProtect();
        System.out.println("穿上"+ ar.getName()+",生命值增加"+ar.getProtect())
    }
}

//测试类
public class Test{
    public static void main(){
        //创建Weapon对象
        Weapon wp = new Weapon("屠龙刀",99999);
        //创建Armour对象
        Armour ar = new Armour("麒麟甲",10000);
        //创建Role对象
        Role r = new Role();
        
        //设置武器属性
        r.setWeapon(wp);//使用屠龙刀,造成99999点伤害
        //设置盔甲属性
        r.wear(); //穿上麒麟甲,生命值增加10000   
    }
}

interface作为成员变量

接口是对方法的封装

//法术进攻
public interface FaShuSkill {
    public abstract void faShuAttack();   
}
//定义角色类
public class Role{
    FaShuSkill fs;
    
    public void setFaShuSkill(FaShuSkill fs){
        this.fs = fs;
    }
    //法术攻击
    public void faShuSkillAttack(){
        System.out.println("发动法术攻击");
        fs. faShuAttack();
        System.out.println("攻击完毕");
    }
}

//定义测试类
public class Test {
    public static void main(){
        //创建游戏角色
        Role role = new Role();
        //设置角色法术技能
        role.setFaShuSkill(new FaShuSkill()){
            @Override
            public void faShuAttack(){
                System.out.println("纵横天下");
            }
        });
        //发动法术攻击
        role.faShuSkillAttack();
        
        //更换技能
        role。setfaShuSkill(new FaShuSkill()){
            @Override
            public void faShuAtttack(){
               System.out.println("逆转乾坤");
            }
        });
            role.faShuSkillAttack();    
    }
}
输出结果:
发动法术攻击:纵横天下
攻击完毕
发动法术攻击
攻击完毕

interface作为方法的参数和返回值类型

我们在看见list接口作为参数或者返回值类型时,可以将ArrayList的对象进行传递或返回

//获取某集合中的所有的偶数
//定义方法
public static list<Integer> getEverNum(List<Integer> list){
    //创建保存偶数的集合
    ArrayList<Integer> evenList = new ArrayList<>();
    //遍历集合list,判断元素为偶数,就添加到evenList中
    for(int i = 0 ; i < list.size(); i++){
        Integer integer = list.get(i);
        if(integer % 2 == 0){
             evenList.add(integer);               
        }
    }
    //返回偶数集合,因为getEvenNum方法的返回值类型是list,而ArrayList是list的子类,所以evenList可以返回
    return evenList;
}
//调用方法
public static Test{
    public static void main(String[] args){
        //创建ArrayList集合,并添加数字
        ArrayList<Integer> srcList = new ArrayList<>();
             for(int i = 0 ; i <10; i++){
                srcList.add(i);
        }
        //获取偶数集合,因为getEvenNum方法的参数是List,而ArrayLis是list的子类,所以srcList可以传递
        List list = getEvenNum(srcList);
        System.out.println(list);

    }
}

猜你喜欢

转载自blog.csdn.net/liu19951104/article/details/81556649
今日推荐