9. 类与对象(下)

面向对象有3个比较重要的思想:封装、继承、多态(也叫OPP语言对的三大特征)
今天我们主要讲封装

封装

封装的定义

封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互

访问限定修饰符

Java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,更符合人类对事物的认知,而访问权限用来控制方法或者字段能否直接在类外使用。Java中提供了四种访问限定符:

Num访问范围privatedefault(默认)protectedpublic
1同一包中同一个类
2同一包中的其他类
3不同包中的子类
4不同包中的非子类
    private String name;//狗的名字
    private int age;//狗的年龄
    private String color;//狗的颜色

再使用set()方法 和 get()方法去访问成员变量
在这里插入图片描述
在这里插入图片描述

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 String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

这样IDEA就会为我们自动生成代码了

建包

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
这时候我们就创建好了

大多数时候字段使用private来修饰,方法使用public来修饰

常见的包

  1. java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
  2. java.lang.reflect:java 反射编程包;
  3. java.net:进行网络编程开发包。
  4. java.sql:进行数据库开发的支持包。
  5. java.util:是java提供的工具程序包。(集合类等) 非常重要
  6. java.io:I/O编程开发包。

static成员

s t a t i c 修饰的拿类名去访问,拿变量名去访问也可以但是非常不推荐!!!(不符合语法) \color{red}{static修饰的拿类名去访问,拿变量名去访问也可以但是非常不推荐!!!(不符合语法)} static修饰的拿类名去访问,拿变量名去访问也可以但是非常不推荐!!!(不符合语法)
s t a t i c 修饰的拿类名去访问,拿变量名去访问也可以但是非常不推荐!!!(不符合语法) \color{red}{static修饰的拿类名去访问,拿变量名去访问也可以但是非常不推荐!!!(不符合语法)} static修饰的拿类名去访问,拿变量名去访问也可以但是非常不推荐!!!(不符合语法)
s t a t i c 修饰的拿类名去访问,拿变量名去访问也可以但是非常不推荐!!!(不符合语法) \color{red}{static修饰的拿类名去访问,拿变量名去访问也可以但是非常不推荐!!!(不符合语法)} static修饰的拿类名去访问,拿变量名去访问也可以但是非常不推荐!!!(不符合语法)

静态变量就定义在成员变量的位置 \color{red}{静态变量就定义在成员变量的位置} 静态变量就定义在成员变量的位置
静态变量就定义在成员变量的位置 \color{red}{静态变量就定义在成员变量的位置} 静态变量就定义在成员变量的位置
静态变量就定义在成员变量的位置 \color{red}{静态变量就定义在成员变量的位置} 静态变量就定义在成员变量的位置

静态方法就定义在成员方法的位置 \color{red}{静态方法就定义在成员方法的位置} 静态方法就定义在成员方法的位置
静态方法就定义在成员方法的位置 \color{red}{静态方法就定义在成员方法的位置} 静态方法就定义在成员方法的位置
静态方法就定义在成员方法的位置 \color{red}{静态方法就定义在成员方法的位置} 静态方法就定义在成员方法的位置
创建一个学生类

Student类

public class Student {
    public String classes;
    public String name;

    public Student(String classes, String name) {
        this.classes = classes;
        this.name = name;
    }
}

Test类

public class Test {
    public static void main(String[] args) {
        Student student1 = new Student("1班","阿漓");
        Student student2 = new Student("1班","阿欢");

    }
}

试想一下现在这个一班一共有50人,这50人都在一班,那么我们需要50遍“一班”,这样去做非常麻烦,于是就有了static来解决这个麻烦

此时代码变动一下

public class Student {
    public static String classes = "1班";
    public String name;

    public Student(String name) {
        this.name = name;
    }
}
public class Test {
    public static void main(String[] args) {
        Student student1 = new Student("阿漓");
        Student student2 = new Student("阿欢");
    }
}

这回通过调用Test,Student类是如何存储的呢?请看下图
在这里插入图片描述
如果确定一直都是1班,那么我们可以将班级写成常量拿final进行修饰

    public static final String classes = "1班";

关于方法的执行顺序:

  1. 先执行静态的【只会执行一次】
  2. 再执行实例的
  3. 再执行构造方法的

内部类

就是在类当中再去定义一个类

1、实例内部类

即未被static修饰的成员内部类

//外部类
class OuterClass {
    public int data1 = 1;
    private int data2 = 2;
    public static int  data3 = 3;

    public OuterClass() {
        System.out.println("外部类的构造方法!");
    }



//    内部类
    class InnerClass {
        public int data1 = 1111;
        public int data4 = 4;
        private int data5 = 5;
        public static final int data6 = 6;

    public InnerClass() {
        System.out.println("内部类构造方法!");
    }

    public void printInnerclass() {
        System.out.println("内部类成员方法打印:"+data1+data2+data3+data4+data5);
        System.out.println("内部类的data1:"+data1);
        System.out.println("外部类的data1:"+OuterClass.this.data1);
    }
}
public void printOuterclass() {
        System.out.println("外部类成员方法打印:"+data1+data2+data3);
    }
}


public class Test {
    public static void main(String[] args) {
        OuterClass outerClass = new OuterClass();
        outerClass.printOuterclass();

        OuterClass.InnerClass innerClass = outerClass.new InnerClass();
        innerClass.printInnerclass();
    }

}

注意事项:

  1. 外部类中的任何成员都可以被在实例内部类方法中直接访问
  2. 实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束
  3. 在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须:外部类名称.this.同名成员来访问
  4. 实例内部类对象必须在先有外部类对象前提下才能创建
  5. 实例内部类的非静态方法中包含了一个指向外部类对象的引用
  6. 外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。

实例内部类
1、实例内部类当中 不能定义静态的成员变量?
     ~~~~      如果定义 ~ 那么这个静态的成员应该是被final修饰的
2、实例内部类当中 ~ 不能定义静态的成员方法!!!
3、如何实例化    ~~    实例内部类??
外部类类名.内部类      ~~~~      变量      ~~~~      =      ~~~~      外部类引用.new      ~~~~      内部类();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
4、如何访问实例内部类 ~ 和 ~ 外部类的同名的成员变量??
       ~~~~~~        OuterClass.this
       ~~~~~~        实例内部类当中 ~ 包含外部类的this
       ~~~~~~       
5、如果是同名的静态的,OuterClass.data3

2、静态内部类

  ~   static   ~   修饰的内部成员类称为静态内部类。

/**
 * 静态内部类:
 *
 */

class OuterClass {
    public int data1 = 1;
    private int data2 = 2;
    private static int data3 = 3;

    public void test() {
        System.out.println(data1+data2+data3);
    }

    /**
     * 1、如何拿到静态内部类的对象???
     * OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
     *
     * 2、不能在静态内部类当中,直接访问外部类非静态成员
     */

    static class InnerClass {
        public int data4 = 4;
        private int data5 = 5;
        private static int data6 = 6;

        public InnerClass() {
            System.out.println("静态内部类的构造方法!");
        }

        public void test() {
            System.out.println("test方法执行了!!");
//            如何拿到外部类的非静态成员呢??
            OuterClass outerClass = new OuterClass();
            System.out.println(outerClass.data1);
            System.out.println(outerClass.data2);
        }
    }
}

public class Test3 {
    public static void main(String[] args) {
        OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
        innerClass.test();

    }
}

局部内部类

定义在外部类的方法体或者{}中,该种内部类只能在其定义的位置使用,一般使用的非常少,此处简单了解下语法
格式。

/**
 * 局部内部类
 */
public class Test4 {
    public static void func() {
        class A {
            public void test() {
                System.out.println("局部内部类!!!");
            }
        }

        A a = new A();
        a.test();
    }

    public static void main(String[] args) {
        func();
    }
}

实际用的并不多,仅做了解即可

注意

  1. 局部内部类只能在所定义的方法体内部使用
  2. 不能被public、static等修饰符修饰
  3. 编译器也有自己独立的字节码文件,命名格式:外部类名字$内部类名字.class
  4. 几乎不会使用

匿名内部类

匿名对象的定义

匿名对象 只能使用一次 用完就销毁

Person类

public class Person {
    String name;
    int age;

    public void test() {
        System.out.println("阿漓");
    }
}

Test类

public class Test {
    public static void main(String[] args) {
        new Person().test();//匿名对象  只能使用一次  用完就销毁
    }
}

匿名内部类的定义

public class Test {
    public static void main(String[] args) {
        new Person() {
            //匿名内部类: 在接口 与 多线程当中用的多
            @Override
            public void test() {
                System.out.println("这是一个匿名内部类");
            }
        };
    }
}

如何调用匿名内部类呢?
在最后.方法名即可

public class Test {
    public static void main(String[] args) {
        new Person() {
            //匿名内部类: 在接口 与 多线程当中用的多
            @Override
            public void test() {
                System.out.println("这是一个匿名内部类");
            }
        }.test();
    }
}

在这里插入图片描述

  • 如何拿到实例内部类的对象???
  • OuterClass.InnerClass innerClass = outerClass.new InnerClass();
  • 1、如何拿到静态内部类的对象???
  • OuterClass.InnerClass innerClass = new OuterClass.InnerClass();

toString方法

@Override//注释:注释+解释【代表这个方法是重写父类的】
    @Override//注释:注释+解释【代表这个方法是重写父类的】
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }

实际上就是将所有的成员变量进行输出打印
在这里插入图片描述
在这里插入图片描述
测试效果:
在这里插入图片描述
因为这里我并没有初始化所以都是一些默认值

也可以写完toString方法以后再写

        System.out.println(person);

看看效果
在这里插入图片描述

在这里插入图片描述

存储规则

局部变量和调用方法在栈上,而成员变量和 n e w 的对象在堆上 \color{red}{局部变量和调用方法在栈上,而成员变量和new的对象在堆上} 局部变量和调用方法在栈上,而成员变量和new的对象在堆上

2022年10月5日17:50:24

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱听歌的阿漓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值