java 封装 (内部类)

目录

一.类与对象

1.this关键字

  概念

   引用当前的实例变量

   调用当前对象的构造函数

用this.在成员方法中调用其他成员方法

2.super关键字 

总结super和this的区别 

二 封装

1.封装的概念

 2.访问限定符

3.常见的包:

4 static成员

5.内部类

简述

5.1 内部类的分类

5.2实例内部类

5.3静态内部类 

5.4 局部内部类

5.5匿名内部类 


一.类与对象

1.this关键字

  概念

         this关键字表示当前对象的引用:

   引用当前的实例变量

   //无参数的构造方法
    public Dog(){

        this("旺旺",8); //传入什么参数类型就与哪个构造方法相匹配。
    }
    //有参数的构造方法
    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void fun(){
        System.out.println(this.name+this.age);
    }

上面代码中 Dog构造函数 和 fun方法中都是用了this关键字来访问当前类的对象,这样可以很清楚的指向那个对象的属性和方法。 

this.name和this.age分别引用了当前对象的name和age实例变量

   调用当前对象的构造函数

class Dog{
    public String name;
    public int age;
    //无参数的构造方法
    public Dog(){
        this("旺旺",8);
    }
    //有参数的构造方法
    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

上面代码中 在无参的构造方法中使用this("旺旺",8), 表示调用当前类另一个带有俩个参数构造方法 ,并且this("旺旺",8);只能放在第一行,否则报错。

⚠️注意 :

  •         不能在类中普通方法中调用this();否则又报错,

  •           this();需要放在当前类的构造方法中的第一行才可以,不然会编译报错不能通过。 

 

  总结:      

1.this();   是只能在当前类构造方法中使用,去调用当前类的其他构造方法。不能在普通的成员方法中使用。

2.只能放在第一行。如果不放在第一行,就不能通过编译

用this.在成员方法中调用其他成员方法

   //有参数的构造方法
    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
        this.fun2("旺旺",15);
    }

    public void fun(){
        System.out.println(this.name+this.age);
    }
    public void fun2(String name, int age){
        this.fun();//在成员方法中调用其他成员方法
    }
​

看到this.既可以在构造方法中去调用其他成员方法,也可以在成员方法中去调用其他成员方法。而且可以写在方法中的任意一行 

2.super关键字 

(super关键字可以说是 “ 为了代码的可读性 ”。记住不管什么时候想要访问子类对象的成员或者方法时使用 this.   访问父类对象的成员和方法时 使用 super.

注意:  只有存在父类的情况下,才会用到super关键字

this(...)用于调用本类构造方法,

super(...)用于调用父类构造方法,

⚠️两种调用不能同时在构造方法中出现

在代码中

class Animal{//这是我们创建的父类Animal
    //父类成员变量
    public String name = "父类name";
    public int age = 99;  //注意父类中有姓名和年龄
 
    //父类成员方法
    public void eat(){
        System.out.println(this.name + "父类正在吃饭");
    }
    public void sleep(){
        System.out.println(this.name + "父类正在睡觉"); //父类中还有吃饭和睡觉
    }
}
class Dog extends Animal{//这是我们创建的子类狗类。让它去继承Animal
    public String name = "子类name";
    public int height = 30;
 
    
    public void show(){
        System.out.println(name);                              //1.子类的
        System.out.println(this.name);                         //2.子类的
        System.out.println(super.name);                        //3.父类的
        System.out.println("父类成员变量age:"+age);       //4.父类的
        System.out.println("父类成员变量age:"+this.age);    //5.父类的
        System.out.println("子类成员变量height:"+height);      //6.子类的
        System.out.println("子类成员变量height:"+this.height); //7.子类的
        eat();            //8.    //子类
        this.eat();       //9.    //子类
        super.eat();      //10.父类
        sleep();          //11.父类
        this.sleep();     //12.父类
        super.sleep();    //13.父类 
        wangWang();       //14.子类
        this.wangWang();  //15.子类
    }
    public void eat(){
        System.out.println(this.name + "子类正在吃饭");
    }
    void wangWang(){
        System.out.println(this.name + "子类喜欢汪汪叫!");
    }
}
 
public class GJiCheng {
    public static void main(String[] args) {
        //用Dog类实例化一个对象
        System.out.println("--------------------------------");
        Dog dog1 = new Dog();
        dog1.show();
        System.out.println("--------------------------------");
    }
}

输出结果:

小结:
1.this访问的时候,既可以访问从父类继承下来的,也可以访问子类自己的

2.super只能访问从父类继承过来的。在子类方法中,如果想要明确访问父类中成员时,借助super关键字即可。

3.当父类和子类有相同的成员变量或成员方法时,可以用super去访问从父类继承过来的,不用super 则访问的是子类自己的那个成员变量或成员方法。

4.super只是一个关键字。提高代码的可读性,让别人轻松知道这是访问父类中的

注意: 当父类与子类有相同的方法名但是参数不同的情况下,我们传入什么参数匹配到那个方法,那么就会访问到哪个方法.(方法的重载)

总结superthis的区别 

相同点:

  1. 都是java的关键字
  2. 都可以在成员方法来访问:成员变量和调用其他的成员方法
  3. 在构造方法调用是,必须在构造方法的第一条语句执行,并且不可以同时存在
  4. 只能在类中的非静态方法中使用,来访问非静态成员和非静态方法

不同点:

  1. this关键字只能对当前对象的引用,super关键字只能对父类对象的引用(继承下来的非静态成员和非静态方法)
  2. 在非静态成员方法中,this用来访问当前类的方法和属性,super用来访问父类继承下来的方法和属性
  3. 在构造方法中,this()用来调用当前类的其他构造方法,super()用来调用父类构造方法,并且两种关键字不可以在构造方法中同时出现
  4. 父类中存在带参的构造方法时,子类的构造方法一定存在super()的调用,用户没有写,编译器也会增加,但是this()的调用需要用户来编写。

二 封装

1.封装的概念

  •         封装从语法上来说 就是被private关键字修饰的成员变量或者方法  只能在当前类使用
  •         封装是指把一个对象的状态信息(也就是属性)隐藏在对象内部,不允许外部对象直接访问对象的内部信息,仅对外公开接口来和对象进行 交互

 2.访问限定符

Java 中主要通过类和访问权限来实现封装: 类可以将数据以及封装数据的方法结合在一起 ,更符合人类对事物的认
知,而 访问权限用来控制方法或者字段能否直接在类外使用 Java 中提供了四种访问限定符:
NO范围private defaultprotectedpublic
1同一个包中的同一类  ✅
2同一个包中的不同类
3不同包的中的子类
4不同包中的非子类
比如:
  • public:可以理解为一个人的外貌特征,谁都可以看得到
  • default: 对于自己家族中(同一个包中)不是什么秘密,对于其他人来说就是隐私了
  • private:只有自己知道,其他人都不知道
  • default权限指:什么都不写时的默认权限

建议:一般情况下成员变量设置为private,成员方法设置为public 

3.常见的包:

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 编程开发包。

4 static成员

1.static修饰成员变量

     static修饰的成员变量,称为静态成员变量 ,静态成员变量最大的特性: 不属于某个具体的对象,是所有对象所共 享的
     静态成员变量特征:
  •         不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
  •         既可以通过类访问,也可以通过对象访问,推荐使用类名访问, 更好的区分 静态变量
  •         类变量存储在方法区当中
  •         生命周期伴随类的一生( 随类的加载而创建,随类卸载而销毁)
        
public class Static {
    private static String name="静态";
    private int age;
    public static void fun(){
        System.out.println("调用静态方法");
    }
    public  void fun1(){
        System.out.println("调用普通方法");
    }
    public static void main(String[] args) {
        Static aStatic = new Static();
        Static aStatic2 = new Static();
        Static aStatic3 = new Static();
        //创建Static实例化 用对象来调用静态成员变量
        System.out.println(aStatic2.name);
        System.out.println(aStatic3.name);
        System.out.println(aStatic.name);
        //使用类名调用静态成员变量
        System.out.println(Static.name);

    }
}

 2.static修饰成员方法

        一般类中的数据成员都设置为private,而成员方法设置为public

        static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的

public class Static {
    public static void fun(){
        System.out.println("调用静态方法");
    }
    public  void fun1(){
        System.out.println("调用普通方法");
    }
    public static void main(String[] args) {
        Static aStatic = new Static();
        //创建Static实例化 用对象来调用静态方法
        aStatic.fun();
        //使用类名调用静态方法
        Static.fun();

    }
}

静态方法的特征:

  1.   在静态方法中 不可以调用非静态成员变量 会报错,也不可以调用非成员静态方法
  2. 可以使用类名调用,也可以使用对象调用 , 推荐使用类名
  3. 不属于某个具体的对象,是类方法

5.内部类

简述

当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服
务,那么这个内部的完整结构最好使用内部类。在 Java 中, 可以将一个类定义在另一个类或者一个方法的内部,
前者称为内部类,后者称为外部类 。内部类也是封装的一种体现。
//Static属于外部类
public class Static {
    //student 属于内部类
    class student{

    }

student类是Static类中新创建的类 属于内部类 

注意 :定义在class 类名{}花括号外部的,即使是在一个文件里,都不能称为内部类

class student{

}
class teacher{
    
}

 // A B是两个独立的类,彼此之前没有关系

5.1 内部类的分类

//Static属于外部类
public class Static {
    //未被static修饰————实例内部类
    class student{

    }
    //被static修饰————静态内部类
    static class teacher{

    }
    public static void fun(){
        class Innerclass{// 在方法定义的内部类————局部内部类

        }

    }
}
根据内部类定义的位置不同,一般可以分为以下几种形式:
        1. 成员内部类 ( 普通内部类:未被 static 修饰的成员内部类 和 静态内部类:被 static 修饰的成员内部类 )
        2. 局部内部类 ( 不谈修饰符 ) 、匿名内部类
注意:内部类其实日常开发中使用并不是非常多,大家在看一些库中的代码时候可能会遇到的比较多,日常开始中使用最多的是匿名内部类。

5.2实例内部类

        没有static修饰的内部成员类称为静态内部类

public class OutClass {
private int a;
static int b;
int c;
public void methodA(){
a = 10;
System.out.println(a);
}
public static void methodB(){
System.out.println(b);
}
// 实例内部类:未被static修饰
class InnerClass{
int c;
public void methodInner(){
// 在实例内部类中可以直接访问外部类中:任意访问限定符修饰的成员
a = 100;
b =200;
methodA();
methodB();
// 如果外部类和实例内部类中具有相同名称成员时,优先访问的是内部类自己的
c = 300;
System.out.println(c);
// 如果要访问外部类同名成员时候,必须:外部类名称.this.同名成员名字
OutClass.this.c = 400;
System.out.println(OutClass.this.c);
}
}
public static void main(String[] args) {
// 外部类:对象创建 以及 成员访问
OutClass outClass = new OutClass();
System.out.println(outClass.a);
System.out.println(OutClass.b);
System.out.println(outClass.c);
outClass.methodA();
outClass.methodB();
System.out.println("=============实例内部类的访问=============");
// 要访问实例内部类中成员,必须要创建实例内部类的对象
// 而普通内部类定义与外部类成员定义位置相同,因此创建实例内部类对象时必须借助外部类
// 创建实例内部类对象
OutClass.InnerClass innerClass1 = new OutClass().new InnerClass();
// 上述语法比较怪异,也可以先将外部类对象先创建出来,然后再创建实例内部类对象
OutClass.InnerClass innerClass2 = outClass.new InnerClass();
innerClass2.methodInner();
}
注意事项
  1. 在实例内部类方法中可直接访问外部类中的任何成员
  2. 实例内部类所处的位置与外部类成员位置相同,因此也受publicprivate等访问限定符的约束
  3. 在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须:外部类名.this.同名成员 来访问
  4. 实例内部类对象必须在先有外部类对象前提下才能创建
  5. 实例内部类的非静态方法中包含了一个指向外部类对象的引用
  6. 外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。

5.3静态内部类 

        被static 修饰的内部成员类称为静态内部类
public class OutClass {
    private int a;
    static int b;
    public void methodA(){
        a = 10;
        System.out.println(a);
    }
    public static void methodB(){
        System.out.println(b);
    }
    // 静态内部类:被static修饰的成员内部类
    static class InnerClass{
        public void methodInner(){
            // 在内部类中只能访问外部类的静态成员
            // a = 100; // 编译失败,因为a不是类成员变量
            b =200;
            // methodA(); // 编译失败,因为methodB()不是类成员方法
            methodB();
        }
    }
    public static void main(String[] args) {
        // 静态内部类对象创建 & 成员访问
        OutClass.InnerClass innerClass = new OutClass.InnerClass();
        innerClass.methodInner();
    }
}
注意事项
        1. 在静态内部类中只能访问外部类中的静态成员
                如果确实想访问,我们该如何做?
        2. 创建静态内部类对象时,不需要先创建外部类对象

5.4 局部内部类

        定义在外部类的方法中的内部类或者{}中———局部内部类

public class OutClass {
    int a = 10;
    public void method(){
        int b = 10;
        // 局部内部类:定义在方法体内部
        // 不能被public、static等访问限定符修饰
        class InnerClass{
            public void methodInnerClass(){
                System.out.println(a);
                System.out.println(b);
            }
        }
        // 只能在该方法体内部使用,其他位置都不能用
        InnerClass innerClass = new InnerClass();
        innerClass.methodInnerClass();
   }
    public static void main(String[] args) {
        // OutClass.InnerClass innerClass = null; 编译失败
    }
}
注意事项
        1. 局部内部类只能在所定义的方法体内部使用
        2. 不能被 public static 等修饰符修饰
        3. 编译器也有自己独立的字节码文件,命名格式:外部类名字 $ 数字内部类名字 .class
        4. 几乎不会使用

5.5匿名内部类 

在Java中,匿名内部类是一种没有名字的局部内部类,它允许我们在使用类的同时定义和实例化它。通常情况下,匿名内部类用于创建一次性的类实例,它可以实现接口或继承抽象类,并且可以覆盖父类或接口的方法。 

  • 没有(或者不需要)命名来初始化类,就称为匿名内部类。
  • 在这四种内部类中,以后的工作可能遇到最多的是匿名内部类,所以说匿名内部类是最常用的一种内部类。
class teacher{
    private String name ;
    void eat(){
        System.out.println("hhh");
    }
}
//Static属于外部类
public class Static {
    public static void main(String[] args) {
        new teacher(){
            @Override
            void eat() { //实现匿名内部类 并重写eat方法
                System.out.println("匿名内部类");
            }
        }.eat();
        new teacher().eat(); //创建匿名对象
    }
}

如何使用匿名内部类:

1.匿名内部类需要依托于其他类或者接口来创建

  •         如果依托的是类,那么创建出来的匿名内部类就默认是这个类的子类
  •         如果依托的是接口,那么创建出来的匿名内部类就默认是这个接口的实现类。

2.匿名内部类的声明必须是在使用new关键字的时候

  •         匿名内部类的声明及创建对象必须一气呵成,并且之后能反复使用,因为没有名字。

匿名内部类特点:

  1. 匿名内部类除了依托的类或接口之外,不能指定继承或者实现其他类或接口,同时也不能被其他类所继承,因为没有名字。
  2. 匿名内部中,我们不能写出其构造器,因为没有名字。
  3. 匿名内部中,除了重写上面的方法外,一般不会再写其他独有的方法,因为从外部不能直接调用到。(间接是调用到的)

interface Work {
    void doWork();
}

public class AnonymousOuterClass {
    private String name = "AnonymousOuterClass";
    private static int age = 21;

    public void say() {
        System.out.println("Say...");
    }

    public static void go() {
        System.out.println("Go...");
    }

    public void test() {
        final int i = 90;
        Work w = new Work() {
            @Override
            public void doWork() {
                //             打印外部类的属性
                System.out.println(AnonymousOuterClass.this.name);
                System.out.println(AnonymousOuterClass.age);
                //              调用外部类的方法实例方法
                AnonymousOuterClass.this.say();
                //              调用外部类的方法静态方法
                AnonymousOuterClass.go();
                //              打印方法里面定义的常量
                System.out.println(i);
            }
        };
        w.doWork();
    }
}

class Test {
    public static void main(String[] args) {
        new AnonymousOuterClass().test();
    }
}

使用匿名内部类实现接口就会变得非常简单

interface Test1 {
    public void method();
}

public class Test {
    public static void main(String[] args) {
        //如果我们需要使用接口中的方法,我们只需要走一步,就是使用匿名内部类,直接将其 类的对象创建出来。
        new Test1() {
            public void method() {
                System.out.println("实现了Test接口的方法");
            }
        }.method();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值