JAVASE 【Java基础五之面向对象2】

本文详细介绍了Java中的面向对象编程概念,包括封装(隐藏数据,提供公共访问方法)、构造器(用于对象初始化)、this关键字(引用当前对象)、继承(子类继承父类的特性)、对象的多态性(子类对象可替代父类对象)以及抽象类和接口(定义规范和标准)。此外,还讲解了静态修饰符、权限修饰符和final关键字的用法,以及对象初始化过程和内部类的相关知识。
摘要由CSDN通过智能技术生成

JAVASE 【Java基础五之面向对象2】

1、封装

1.1含义

将对象中数据或代码逻辑隐藏起来。对数据的操作在类的内部完成,对外界隐藏实现的细节。

1.2好处

  • 对象(或组件)内部代码实现的细节可以对外隐藏。
  • 简化外部使用对象时的操作难度。外部使用对象时,调用对象暴露出来的方法即可。
  • 让整个系统的开发组件化、模块化程度更高,更有利于实现:高内聚、低耦合。

1.3示例

public class MarryObject {

    // 将属性的权限修饰符设置为私有,不允许外部直接访问
    private int age;

    // 对外暴露的获取数据的getXxx()方法
    public int getAge() {
        return age;
    }

    // 对外暴露的设置数据的setXxx()方法
    public void setAge(int ageOutter) {

        // 在方法内部,根据内部的逻辑,对外界数据进行修正
        if (ageOutter < 20) {

            age = 20;

        } else if (ageOutter > 60) {

            age = 60;

        } else {

            age = ageOutter;

        }

    }

}

2、构造器

注意:构造器和方法是两码事,各是各的。

  • 2.1构造器引入

当我们使用new关键字创建一个类的对象时,就是在使用这个类的构造器了:

在这里插入图片描述

如果我们没有明确声明构造器,那么系统回给类分配一个隐式的构造器。
在这里插入图片描述

2.2构造器的作用

  • 作用1:创建对象。
  • 作用2:在创建对象的过程中,对类进行初始化操作。这些操作写在构造器的大括号中。
    • 初始化操作放到构造器里面,由构造器自动完成,程序员就不必在创建对象后还想着对这对象做初始化操作。

2.3构造器的组成部分

在这里插入图片描述

2.4构造器的参数

[1]有一个参数构造器例子

public class Soldier {

    private String soldierName;

    public Soldier(String soldierName) {
        this.soldierName = soldierName;
    }

}

注意:当类中声明了有参构造器之后,系统将不再给这个类分配无参的构造器。

[2]一个类可以有多个构造器

根据参数列表不同,多个构造器之间是重载关系。规则和方法重载一致:

  • 要么参数个数不同
  • 要么参数类型不同
public class Soldier {

    private int age;
    private String soldierName;
    private String weapon;
    private String gender;

    public Soldier() {
        
    }
    
    public Soldier(int age) {
        this.age = age;
    }

    public Soldier(String soldierName) {
        this.soldierName = soldierName;
    }
    
    public Soldier(String soldierName, String weapon) {
        this.soldierName = soldierName;
        this.weapon = weapon;
    }
    
    public Soldier(String soldierName, String weapon, String gender) {
        this.soldierName = soldierName;
        this.weapon = weapon;
        this.gender = gender;
    }
    
    public Soldier(int age, String soldierName, String weapon, String gender) {
        this.gender = gender;
        this.weapon = weapon;
        this.soldierName = soldierName;
        this.age = age;
    }

}

2.5构造器相关语法规则

  • Java语言中,每个类都至少有一个构造器
  • 默认构造器的修饰符与所属类的修饰符一致
  • 一旦显式定义了构造器,则系统不再提供默认构造器
  • 一个类可以创建多个重载的构造器
  • 父类的构造器不可被子类继承

3、this关键字

  • 3.1含义
  • 类的方法中:代表调用当前方法的对象
    在这里插入图片描述

  • 类的构造器中:代表当前构造器正在创建的对象
    在这里插入图片描述

  • 3.2this能干什么

[1]调用属性

System.out.println("我的年龄:" + this.age);
System.out.println("我的姓名:" + this.soldierName);
System.out.println("我的武器:" + this.weapon);

[2]调用方法

System.out.println("我的性别:" + this.getGender());

[3]调用构造器

在类中的某个构造器中调用这个类的其他构造器:

public class Tiger {

    private String tigerName;
    private int tigerAge;

    public Tiger() {
        System.out.println("这里是Tiger类的无参构造器");
    }

    public Tiger(String tigerName) {

        this();

        this.tigerName = tigerName;

        System.out.println("这里是Tiger类的一参构造器");

    }

    public Tiger(String tigerName, int tigerAge) {

        this("aaa");

        this.tigerName = tigerName;
        this.tigerAge = tigerAge;

        System.out.println("这里是Tiger类的两参构造器");
    }
}

[4]this调用构造器的规则

  • 在构造器中调用其他构造器,this()语句必须在第一行
    在这里插入图片描述

  • 各个构造器之间调用不能形成闭环

在这里插入图片描述
循环调用逻辑如下:
在这里插入图片描述

  • 一个构造器中调用其他构造器的操作只能有一个

4、继承

  • 4.1 程序中的继承

    在程序中,也能出现继承的关系,让一个类去继承另一个类.

比如 A类继承B类

  • 出现继承的关系
  • A类是B类的子类,或者称为派生类
  • B类是A类的父类,或者称为超类,基类
  • 子类可以直接拥有父类的成员(不是全部)
  • 9.2 继承的语法格式

    继承使用关键字 extends,表示继承的意思

    注意: extend 本身含义,扩展,延伸

  • 定义格式

    class B{}
    class A extends B{}  // A 继承 B类
    
  • 继承的入门案例 – 子类拥有父类成员

    /**
     *  定义的是 Teacher和Manager类的共性内容
     *  姓名年龄
     */
    public class Person {
        String name ;
        int age;
    }
    
    /**
     *  管理类,班主任类
     */
    public class Manager extends Person{
    
    }
    
    
    /**
     *  老师类
     *  重复,只做一次
     *  想法:
     *    String name;
     *     int age;
     *  换一个地方定义(共性抽取)
     *  Teacher和Manager共用
     *  使用Person中的成员
     *  Teacher继承Person
     */
    public class Teacher extends Person{
    
    }
    
        public static void main(String[] args) {
            /**
             *  创建对象, Person的子类对象
             *  Person : Teacher,Manager
             */
            Teacher teacher = new Teacher();
            //teacher对象,调用成员变量
            //teacher子类对象调用继承的成员变量
            teacher.name = "张三";
            teacher.age = 20;
    
            Manager manager = new Manager();
            manager.name = "李四";
            manager.age = 22;
    
            System.out.println("teacher.name = " + teacher.name);
            System.out.println("teacher.age = " + teacher.age);
    
            System.out.println("manager.name = " + manager.name);
            System.out.println("manager.age = " + manager.age);
        }
    
  • 4.3 继承的好处

    上面案例,使用程序中的继承,使用继承的好处:

  • 减少代码量

  • 复用性提高

  • 继承的存在,导致了面向对象的最后一个特征多态

    继承有弊端: 类和类之间的紧密性更强.(扩展性越差)

  • 4.4. 继承后成员特点

  • [1]继承后成员变量特点

子类和父类中的成员变量同名

  • 调用的使用: 子类自己有,使用自己的,子类没有,使用父类

    public class Fu{
        String s = "父类";
    }
    
    public class Zi extends Fu{
        String s = "子类";
    }
    
    public static void main(String[] args) {
        //创建对象,子类对象
        Zi zi = new Zi();
        //子类对象,调用成员s
        System.out.println(zi.s);
    }
    
  • [2] super关键字

    super关键字是超级的意思,在子类中调用父类的成员,使用此关键字

super.变量  调用父的成员变量
super.方法() 调用的是父类的成员方法

this表示当前对象,super表示父类在内存中的存储空间,不是对象

public  class Fu{
    String s = "父类";
}
public class Zi extends Fu {
    String s = "子类";

    public void print(){
        String s = "方法";
        System.out.println(s);
        System.out.println(this.s);
        System.out.println(super.s);
    }
}
public static void main(String[] args) {
    //创建子类对象,调用方法
    Zi zi =  new Zi();
    zi.print();
}
  • [3] 继承后成员方法特点

    **方法重写override:**子类父类出现了一模一样的方法,称为子类重写了父类的方法.又称为覆盖或者复写.

    调用子类重写的方法,假如子类没有重写,调用父类的方法

public class Fu {
    public void print(){
        System.out.println("父类方法print");
    }
}
public class Zi extends Fu {
    /**
     * 要重写父类的方法
     * 直接复制
     */
    public void print(){
        System.out.println("子类方法print::重写");
    }
}
    public static void main(String[] args) {
        //创建子类对象
        Zi zi = new Zi();
        zi.print();
    }
  • [4] 方法重写的意义

    继承本质是扩展的意思,延伸的意思,依靠方法的重写来实现

方法重写引入案例,理解重写的意义

/**
 *  定义手机类
 *  早年代手机
 */
public class Phone {
    /**
     * 定义手机的来电显示功能
     * 数字移动电话
     */
    public void showingCall(){
        System.out.println("来电显示号码");
    }
}

/**
 *  新手机:
 *  功能变强,但是原有功能继续复用
 *  继承和方法重写的思想
 */
public class Iphone extends Phone {
    //重写父的方法
    //方法名字不变,用户不需要重新知
    public void showingCall(){
        //复用显示号码功能,父类的方法中,已经完成了
        //调用父类的方法
        super.showingCall();
        //新增的功能
        System.out.println("显示大头像");
        System.out.println("归属地");
        System.out.println("意思推销");
    }
}
public static void main(String[] args) {
    //创建手机对象
    Phone phone = new Phone();
    phone.showingCall();
    System.out.println("==========");
    //创建新手机对象
    Iphone iphone = new Iphone();
    iphone.showingCall();
}
  • [5] 方法重写小问题

方法重写需要考虑权限的.保证子类方法的权限要大于或者等于父类方法权限

  • 父类的方法权限是public

    class Fu{
        public void print(){}
    }
    class Zi extends Fu{
        public void print(){} //正确
        protected void print(){} //错误,权限降低
        void print(){} //错误,权限降低
        private void print(){} //错误,权限降低
    }
    
  • 父类的方法权限是protected

    class Fu{
        protected void print(){}
    }
    
    class Zi extends Fu{
        public void print(){} //正确
        protected void print(){} //正确
        void print(){} //错误,权限降低
        private void print(){} //错误,权限降低
    }
    
  • 父类方法权限是默认

    class Fu{
         void print(){}
    }
    
    class Zi extends Fu{
        public void print(){} //正确
        protected void print(){} //正确
        void print(){} //正确
        private void print(){} //错误,权限降低
    }
    
  • 如果父类的方法权限是private, 子类不知道该方法的存在,没有继承的说法

  • [6] 继承后构造方法特点

构造方法特点: 子类的构造方法中,第一行存在隐式代码 (写不写都存在),代码是super(); 调用父类的无参数构造方法.

public class Fu  {
    public Fu(){
        System.out.println("父类构造方法");
    }
}
public class Zi extends Fu {
    public Zi(){
        super(); //调用父类的无参数构造方法.
        System.out.println("子类构造方法");
	}
}
  • 子类的构造方法,无论重载多少个,第一行肯定也是super();
public class Zi extends Fu {
    public Zi(){
        super(); //调用父类的无参数构造方法.
        System.out.println("子类构造方法");
    }

    public Zi(int a){
        super(); //调用父类的无参数构造方法.
        System.out.println("子类构造方法::重载的");
    }
}
  • 父类没有无参数构造方法,子类的构造方法中,super(传递参数)
  • 父类中存在多个构造方法,子类的构造方法只要调用到其中的一个即可
public class Fu  {
    /**
     * 父类的构造方法
     * 加上参数,有参数的构造
     */
    public Fu(int a){
        System.out.println("父类构造方法" + a);
    }

    public Fu(String s){
        System.out.println("父类构造方法" + s);
    }
}

public class Zi extends Fu {

    public Zi(){
        //调用父类的无参数构造方法
        //父类中没有无参数构造
        //传递响应的参数
        super(7);
    }

    public Zi(String s){
        //调用父类构造方法,保证调用其中一个
        super("字符串");
    }
}
  • 4.5继承特点

[1]单继承

一个类只能继承一个类,不允许同时继承多个类

class A extends B,C{} //不允许的行为

单继承存在局限性,解决局限性问题,接口的概念

[2]多层继承

class A extends B{}
class B extends C{}
//多层继承,允许实现
//class C extends Object{}

A类可以同是拥有B和C的成员, B只能拥有C的成员

A类中super调用的是B类成员,如果B类没有成员,调用C成员

Object类是java中的皇帝,所有的类都是Object子类

5、对象的多态性

引入 : 生活中的多态性! 你自己的身份是学生,你的身份职场精英,患者.在不同的时期不同环境,状态是不同的.

生活中的多态性: 一个事物具备的不同形态.

5.1 对象多态性前提

  • 必须有继承或者是接口实现
  • 必须有方法的重写

多态的语法规则: 父类或者接口的引用指向自己的子类的对象

父类 变量(对象名)  =  new 子类对象(); //多态写法

对象调用方法,执行的子类的方法重写

5.2 多态中成员的特点

  • 多态中成员变量的特点

    • 编译 : 父类中没有成员变量,编译失败
    • 运行 : 运行父类中的成员变量
  • 多态中成员方法的特点

    • 编译 : 父类中没有成员方法,编译失败
    • 运行 : 运行子类的方法重写
  • 简练 : 成员方法编译看左边,运行看右边.成员变量都是左边

    Person p = new Student();

public class Person {
   String s = "父类成员";

   public void eat(){
       System.out.println("人在吃饭");
   }
}
public class Student extends Person {
    String s = "子类成员";

    public void eat(){
        System.out.println("学生吃饭");
    }
}
    public static void main(String[] args) {
        Person p = new Student();
        //对象p,子类对象,调用成员变量s
        System.out.println(p.s);
        //子类对象调用方法
        p.eat();
    }

在这里插入图片描述

5.3 多态的转型

多态的程序中,不能调用子类的特有成员!!

只能调用子类父类的共有成员!!

转后类型 变量名 = (转后类型)要转的数据; //公式
 public static void main(String[] args) {
     //创建对象,多态性
     //父类 = new 任意子类对象() 扩展
     Animal animal = new Cat();
     animal.eat();
     //Cat类的特有功能 catchMouse()方法
     //类型转换,强制
     //Cat提升为了Animal,转回Cat类型
     Cat c = (Cat)animal;
     c.catchMouse();
 }

在这里插入图片描述

补充: 多态性提升扩展性,是否需要强制转换,根据实际功能需求来决定.

5.4 多态中的转型异常

异常ClassCastException 类型转换异常,在多态中经常发生.

是在进行类型的强制转换的时候发生,我们现在的案例是Dog不能转成Cat.

需要解决这个异常 : 对象是Cat转Cat,是Dog换Dog

运算符 : 比较运算符,结果是boolean类型

运算符是关键字 instanceof

instanceof的语法格式:

对象名 instanceof  类的名字
解析: 比较这个对象,是不是由这个类产生的
c instanceof Cat  解释: c对象是不是Cat类产生的,如果是结果就是true

强制类型转换之前的安全性判断

public static void main(String[] args) {
    //多态创建对象
    Animal animal = new Dog();
    animal.eat();
    //判断 animal是不是Cat类的对象
    //boolean b = animal instanceof Dog ;
    //System.out.println(b);
    //调用子类的特有方法
    if (animal instanceof Cat){
        //if为true,强制转换为Cat
        Cat c = (Cat)animal;
        c.catchMouse();
    }
    if (animal instanceof Dog){
        Dog d = (Dog)animal;
        d.lookHome();
    }
}
  • 抽象类 abstract

抽象的概念 : 凡是说不清楚的都是抽象

例子 : 我买了一台手机,买了一直笔,都是抽象概念.

具体: 华为Meta40Pro ,金属, 16G+512

程序中 : 我知道这个功能存在,但是怎么完成就说不清楚,程序中也出现了抽象.

6、 抽象

6.1方法定义

使用关键字 abstract定义抽象方法

权限修饰符 abstract 返回值类型 方法名字(参数列表) ;
abstract关键字
抽象方法没有方法体, 不需要{},直接分号结束

当一个类中的方法是抽象方法的时候,这个类必须是抽象类,在类的关键字class前面使用abstract修饰.

public abstract class 类名{}
public abstract class Animal {
    /**
     * 动物吃什么?
     * 说不清楚,抽象,可以不说
     */
    public abstract void eat();
}

6.2 抽象类的使用方式

  • 抽象类不能实例化对象,不能new对象.
    • 为什么不能建立对象,类中有没有主体的方法存在,建立对象调用抽象方法是绝对的错误,因此不能建立对象.
  • 需要子类继承抽象类,重写抽象方法.
  • 创建子类对象
  • 使用多态性创建对象,调用方法执行子类的重写
public class Cat extends Animal{

    /**
     * 重写父类的方法
     * 去掉修饰符 abstract
     * 添加主体 {}
     */
    public  void eat(){
        System.out.println("猫吃鱼");
    }
}
public static void main(String[] args) {
    //创建Animal的子类对象
    Animal animal = new Cat();
    //eat方法不可能执行父类,运行子类的重写
    animal.eat();
}

6.3 抽象类中成员的定义

[1]抽象类中能否定义成员变量

可以定义成员变量,成员变量私有修饰,提供方法 get/set,由子类的对象使用

public abstract class Animal {
    //抽象类中能否定义成员变量
    private String name;
    public abstract void eat();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public static void main(String[] args) {
    Animal animal = new Cat();
    animal.eat();
    //animal对象调用方法 get/ set
    animal.setName("tom");
    String name = animal.getName();
    System.out.println(name);
}

[2] 抽象类中有构造方法吗

抽象类中有构造方法,不写有默认的

public abstract class Animal {

    public Animal(){
        System.out.println("Animal的构造方法");
    }

    public Animal(String name){
        this.name = name;
        System.out.println("有参数String的构造方法");
    }

    //抽象类中能否定义成员变量
    private String name;
    public abstract void eat();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class Cat extends Animal {

    public Cat(){
        //调用父类的有参数构造方法
        super("张三");
    }

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

[3] 抽象中能否不定义抽象方法

抽象类中,可以不定义出抽象方法.

但是,如果有抽象方法存在,这个类必须是抽象类

6.4 子类还是抽象类的问题

当一个子类继承一个抽象类的时候,子类必须重写全部的抽象方法.假如子类重写了部分抽象方法,这个子类依然还是抽象类.

public abstract class Animal {
    public abstract void eat();
    public abstract void sleep();
}
/**
 * Cat继承父类Animal,Cat类拥有了父类的成员
 * 父类有什么,我就有什么
 */
public abstract class Cat extends Animal {
    public  void eat(){}
    /**
     * 方法sleep没有重写
     * 还是一个抽象的方法
     */
//    public abstract void sleep();
} 

7、接口 interface

7.1 接口无处不在

身边的接口有哪些,笔记本上USB接口,HDMI,TypeC接口,插座

USB接口 : 连接鼠标,键盘,摄像头,手机,移动硬盘,电风扇.设备的工作原理不同,但是都可以连接到USB接口上,完成他的任务.说明了一个问题 : 这些设备都满足USB的接口规范!!

接口:就是一个规范,或者称为标准 , 无论什么设备,只要符合接口标准,就可以正常使用.

接口的扩展性很强大.

7.2 Java中接口定义

当一个抽象类中的所有方法全部是抽象的时候,可以将这个抽象类换一个更加贴切的名词,叫他接口. 接口是特殊的抽象类.

定义接口,使用关键字 interface

语法规范:

public interface 接口名{}

接口在编译后,依然还是.class文件

7.3 接口中成员定义 (JDK1.7 版本)

  • 成员变量

    • 成员变量的定义是具有固定格式

    • 成员变量的修饰符是固定 public static final

      public static final 数据类型  变量名 =;
      
  • 成员方法

    • 成员方法的定义是具有固定格式

    • 成员方法的修饰符固定为 public abstract

      public abstract 返回值类型 方法名(参数列表) ;
      

7.4接口的使用方式

  • 接口不能建立对象,不能new
  • 需要定义类,实现接口(继承类,在接口中称为实现,理解为继承)
    • 实现接口,使用新的关键字 implements
    • 实现的格式 class 类 implements 接口名{}
  • 重写接口中的抽象方法
  • 创建子类的对象
/**
 *  定义好的接口
 */
public interface MyInterFace {
    //接口的成员变量
    public static final int A = 1;
    //接口的成员方法
    public abstract void myInter();
}
/**
 *  定义MyInterFace接口的实现类
 *  重写接口的抽象方法
 */
public class MyInterFaceImpl implements MyInterFace{
   public void myInter(){
       System.out.println("实现类实现接口,重写方法");
    }
}
public static void main(String[] args) {
    //创建对象,多态性,创建接口实现类的对象
    MyInterFace my = new MyInterFaceImpl();
    my.myInter();
    //输出接口中的成员A的值
    System.out.println(my.A);
}

接口的多实现

类和类之间单继承,局限性的问题.接口的出现,是对单继承的改良,允许一个类同时实现多个接口.

语法格式:

class 类名 implements 接口A,接口B{}

实现类,重写实现的多有接口中的抽象方法

public interface A {
    public abstract void a();
}
public interface B {
    public abstract void b();
}
/**
 *  实现接口A和B
 */
public class C implements A,B{
    @Override
    public void a() {
        System.out.println("重写A接口方法");
    }

    @Override
    public void b() {
        System.out.println("重写B接口方法");
    }
}

public static void main(String[] args) {
    C c = new C();
    c.a();
    c.b();
}

8、 静态修饰符

static修饰符 : 最早出现在main方法中.只能修饰成员,不能写在方法的内部,被static修饰的成员,静态成员变量和静态的成员方法.

  • 8.1、 静态修饰成员变量

    static 修饰的成员变量,是被所有的对象共享的数据.没有被static修饰的成员变量,是每个对象的独享数据或者是特有数据.
    在这里插入图片描述

public class Person {
    String name;
    static String country = "中国";
}
public class StaticTest {
    public static void main(String[] args) {
        Person p1 = new Person();
        p1.name = "张三";
        Person p2 = new Person();
        p2.name = "李四";
        //使用对象p1修改变量country的值
        p1.country = "美国";
        System.out.println(p2.country);
    }
}
  • 8.2、 静态内存
  • 静态成员内存的特点
    • 静态成员跟随自己的类进入到元数据区(静态区域)
    • 静态成员属于自己的类,不属于对象
    • 静态成员进入内存后,赋默认值
    • 静态成员变量的初始化实际早于对象

在这里插入图片描述

  • 8.3、 静态成员的调用方式

    静态的内存图中,已经很明白了,静态属于自己的类,不是对象,静态的调用方式应该是类名.静态成员

Person.country ;//调用静态成员
public static void main(String[] args) {
    System.out.println(Person.country);
    Person p1 = new Person();
    p1.name = "张三";
    Person p2 = new Person();
    p2.name = "李四";
    //使用对象p1修改变量country的值
    Person.country = "美国";
    System.out.println(Person.country);
}

静态的调用方式是两种 : 类名调用,对象调用. 非静态成员调用只能对象.

静态成员调用方式只有类名. 非静态成员只能对象. 对象.静态调用方式,会被javac编译为类名调用.

  • 8.4、 静态方法

    静态方法直接类名调用. 静态方法中不能直接使用非静态成员.

    为什么不能调用非静态成员

静态是先人,非静态是后人. 静态出现在内存的时间早于非静态

public class Person {
    String name;
    static String country = "中国";

    /**
     * 静态方法
     */
    public static void eat(){
        System.out.println("人在吃饭" + country);
        System.out.println(name); //错误写法,不允许
    }
}

静态内存优先于对象,在静态的方法中不能使用this和super

  • 8.5 、main方法
public static void main(String[] args){
    
}
  • main方法详解
    • public 最大权限 : main方法的调用者是JVM
    • static 无需对象,被类名直接调用,JVM启动的时候使用类名.main启动程序
    • void 无返回值,调用者是JVM,方法的返回值都是返回给调用者,JVM不需要返回值,没有意义
    • main 固定方法名称
    • args 字符串的数组,JVM调用方法main必须传递参数,后期对JVM设置参数
  • 8.6、 什么时候定义静态
  • 静态成员变量 : 具体功能具体分析 .
    • 当你需要定义一个类的时候,分析这个类new出来的对象,是否存在共享数据,如果有共享数据,应该定义为静态变量
  • 静态成员方法 :
    • 当你类中的方法,没有使用过非静态成员你的时候,应该定义为静态.

10、 四大权限

四大权限 public protected default private

privatedefaultprotectedpublic
同一类OKOKOKOK
同一包NOOKOKOK
不同包子类NONOOKOK
不同包非子类NONONOOK
  • 受保护权限 protected
    • 权限的成员,为子类提供使用
    • Object类是所有类的父类,类中的方法权限有public,protected
    • 关键的方式受保护权限的方法只能是 子类中super调用!!
    • 子类对象不能调用,不出子类

11、 final修饰符

final修饰符是最终的意思,不可改变.final可以修饰类,修饰方法,修饰成员变量,修饰局部变量.

  • 11.1、 final修饰类

    被final修饰的类,称为最终类,不能被其他的类继承,无子类. 太监类.

    学过的final类有哪些, String,System,Scanner.

public final class A{} //这个类A,不能出现子类,如果继承,直接报错
public class B extends A{} //错误,编译错误,最终类不能继承
  • 11.2、 final修饰方法

    被final修饰的方法,最终方法,不能被子类重写,和调用无关.

    一个类中的部分方法很完美,但是另一部分方法有待完成,设计为两个部分.完美的方法就是final

public class A{
    public final void a(){} //方法不能被子类重写
}
public class B extends A{
    public void a(){} //最终方法,不能重写
}
  • 11.3、 final修饰局部变量

    变量定义在方法的内部,是局部变量, 被final修饰后,一次赋值,终身不改变,锁死了变量的值,看做是常量.

  • final修饰的基本类型,锁死值
  • final修饰的引用类型,锁死内存地址 (引用类型中的成员不受影响)
  • final修饰了方法的参数,调用者传递值后,方法的参数值就锁死
public static void main(String[] args) {
    /**
    *   Student student 对象存储的是内存地址
    *   final修饰后,固定住的,不可改变是student变量保存的地址
    *   但是,Student对象中的成员,不受影响
    */
    final  Student student = new Student();
    student.age = 20;
    student.age = 30;
    System.out.println(student.age);

    final int[] arr = {1,2,3};//arr变量的值,固定为内存地址,不可改变
    arr[1] = 200;

    show(5);
    }

    public static void show(final int x){
    	x = 6; //final修饰,不可改变,报错
    }
}
  • 11.4、 final修饰成员变量

    成员变量的定义位置,是在类中,方法外面.成员变量在内存中有默认值.final修饰成员变量的时候,锁住的不是内存默认值,而是我们程序人员手动的赋值.

  • 成员变量赋值,可以定义直接写值 int age = 0;
  • 成员变量赋值,可以使用构造方法 public Student(int age){this.age=age;}
  • 成员变量赋值,可以使用set方法完成
    • final修饰的成员变量,可以构造方法赋值,不能set方法赋值
    • 构造方法在new对象的时候,执行一次,仅仅一次
    • 可set方法,反复执行!!
public class Student {
    final int age ;

    public Student (int age ){
        this.age = age;
    }

   /*public void setAge(int age){
       this.age = age;
   }*/
}

12、 代码块

  • 12.1 静态代码块

    写在类中方法外面 : static{}

静态代码块的执行时机 : 只要使用了这个类的成员(new对象,调用静态方法,静态变量),静态代码块就会执行,而且就一次

后面的课程会自己写静态代码块 : 数据库连接池 (C3P0,Druid)

JDBC注册数据库驱动程序,使用代码块

  • 12.2 构造代码块

    写在类中方法外面的 {}, 创建对象的时候运行,new一次,运行一次

  • 12.3 局部代码块

    写在方法内部的 {} 局部代码块,没有用

13. 对象的初始化过程(子类和父类)

  • 父类.class文件先进入内存
  • 子类.class文件再进入内存
  • 初始化父类的静态成员(变量,代码块,方法)
  • 初始化子类的静态成员
  • 运行父类的静态代码块
  • 运行子类的静态代码块
  • 运行父类的构造代码块
  • 运行父类的构造方法
  • 运行子类的构造代码块
  • 运行子类的构造方法

14. 内部类

概述 : 所谓内部类,就是在一个类的内部,定义了另外的一个类

class A{ //外部类,封闭类
    class B{} //内部类,嵌套类
}

对象是生活中的存在的事物,一个事物中还存在着另一个具体的事物

class 大楼{
    class 电梯{}
}
  • 14.1、 成员内部类

    成员内部类,是一个类定义在了另一个类的成员位置.这个内部类可以使用成员修饰符,public static final private .

    对于内部来说 : 可以直接使用外部类的成员,如果外部类要使用内部类的成员,必须要创建对象.

//公式 : 外部类名.内部类名 = new 外部类对象().new 内部类对象()

//外部类
public class Outer {

    public void outer(){
        System.out.println("外部类的方法outer");
    }

    //内部类
    public class Inner{
       public void inner(){
           System.out.println("内部类的方法inner");
       }
    }
}
public static void main(String[] args) {
    //调用内部类的方法inner()
    Outer.Inner oi = new Outer().new Inner();
    oi.inner();
}

问题 : 内部类Inner,编译后有class文件吗?有class文件,名字是外部类$内部类

内部类也是类,继承Object,可以实现接口

内部类是静态的调用方式 : 外部类名.内部类名 变量名 = new 外部类.内部类()

  • 14.2、 局部内部类

    局部内部类 : 要定义在方法里面. 方法里面是局部位置,不能使用成员修饰符,权限,静态不能用

class A{
    public void a(){
        class B{} //局部内部类
    }
}
public class Outer {
    /**
     *  Inner类,是方法Outer的局部
     *  依然方法,才能被外界访问
     */
    public void outer(){
        class Inner{
            public void inner(){
                System.out.println("局部内部类的方法!!");
            }
        }
        //方法,建立对象
        Inner inner = new Inner();
        inner.inner();
    }
}
public static void main(String[] args) {
    //调用内部类的方法inner()
    //直接调用,不能调用
    Outer outer = new Outer();
    outer.outer();
}

局部内部类,访问局部变量,变量必须final修饰

  • 14.3、 匿名内部类

    匿名内部类,就是没有名字的内部类,只能写在方法中,为了简化代码书写.

    简化 : 实现类,实现接口,重写方法,创建对象. 或者是子类继承父类,重写方法,创建对象.代码上少内容.

  • 匿名内部类使用的前提 :

    • 必须有接口实现,或者是类的继承

    • 格式 :

      new 接口或者父类(){
          //重写抽象方法
      };
      格式 == 实现类,实现接口,重写方法,创建对象
      
    public interface MyInter {
        public abstract void inter();
        public abstract void inter2();
    }
    
    public class InnerClassTest {
        public static void main(String[] args) {
            //匿名内部类,简化书写,不写实现类
            //同时调用多个重写方法
            /*
             *  new MyInter(){}; 是接口实现类的匿名对象
             * 多态 : 接口 变量 = 实现类对象
             */
           MyInter my =  new MyInter(){
    
                @Override
                public void inter() {
                    System.out.println("实现类实现接口重写方法");
                }
    
                @Override
                public void inter2() {
                    System.out.println("实现类实现接口重写方法2222");
                }
            };
           my.inter();
           my.inter2();
        }
    }
    

15、非法修饰符组合

非法的修饰符的组合,主要说的是抽象abstract

  • abstract和private就是非法组合,抽象方法要重写,private不能继承
  • abstract和final就是非法组合,抽象方法要重写,final修饰不能重写
  • abstract和static就是非法组合,静态方法类名直接调用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值