自学内容网 自学内容网

JavaSE语法阶段复习知识整理3之封装

前言:
面向对象程序三大特性:封装、继承、多态。本篇博客主要整理了面向对象之封装的概念,四种访问限定符,包的概念及创建包的操作,包访问权限控制举例,静态成员变量,静态成员方法,静态成员变量的初始化,代码块


一、封装

1.1 封装的概念

 封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互
 Java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,更符合人类对事物的认知,而访问权限用来控制方法或者字段能否直接在类外使用。


1.2 访问限定符

 Java中提供了四种访问限定符:privatedefaultprotectedpublic

在这里插入图片描述
private:只能在当前类使用
default:使用这个限定符,什么也不加,代表是包访问权限,只能在当前包中被访问
protected:可以在同一个包中被访问,或者不同包中的子类中可以被访问(需要注意的是,在修饰变量或方法时并不是在前面写上default,而是什么也不写)
public:同一个包,不同的包中都可以被访问

代码示例如下:

public class Test {
    class Animal {
        public String name;//可以被公开访问和使用
        String color;//包访问权限,只能在同一个包中被访问
        private int age;//只能在当前类中被访问
        protected String sex;//在当前包中被访问,或者在当前类的子类中被访问
    }
}

1.3封装扩展之包

  包的概念
    包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,比如:一个包中的类不想被其他包中的类使用。包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在不同的包中即可
  导入包中的类
    我们常说的导包,其实是导入包中的某个类。比如要使用Scanner类创建一个对象时,需要用import导入这个类。这里的 java.util就是类所在的包, Scanner就是用到的类。

public class Test {
public static void main(String[] args) {
    java.util.Scanner scan = new java.util.Scanner(System.in);
  }
}

但是这样写比较麻烦,可以使用import语句导入包

import java.util.Scanner;
public class Test {
public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
  }
}

  通配符 *

使用通配符,import java.util.*,如果用到了util底下的某个类,就会加载相对应的类,所以不用担心一次把里面所有类全部加载完
如果要使用java.util中的多个类甚至所有类,可以使用import java.util.*,但是不推荐,容易出现冲突的情况,比如以下代码:

import java.util.*;
import java.sql.*;
public class Test {
public static void main(String[] args) {
// util 和 sql 中都存在一个 Date 这样的类, 此时就会出现歧义, 编译出错
   Date date = new Date();
   System.out.println(date.getTime());
}
}

编译出错
对Date的引用不明确java.sql 中的类 java.sql.Datejava.util 中的类 java.util.Date 都匹配

在这种情况下应该使用完整的类名,代码示例如下:

import java.util.*;
import java.sql.*;
public class Test {
public static void main(String[] args) {
    java.util.Date date = new java.util.Date();
    System.out.println(date.getTime());
}
}

  自定义包
基本规则

  • 在文件的最上方加上一个 package 语句指定该代码在哪个包中.
  • 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.baidu.demo1 ).
  • 包名要和代码路径相匹配. 例如创建 com.bit.demo1 的包, 那么会存在一个对应的路径 com/baidu/demo1 来存储
    代码.
  • 如果一个类没有 package 语句, 则该类被放到一个默认包中.

操作步骤

  1. 右键src,选择New,再点击Package
    在这里插入图片描述

  2. 输入包的名称,回车(注意包名应全部为小写字母)
    在这里插入图片描述

  3. 此时可以看到我们的磁盘上的目录结构已经被 IDEA 自动创建出来了
    在这里插入图片描述

  4. 同时我们也看到了, 在新创建的 Test.java 文件的最上方, 就出现了一个 package 语句,说明Test类所在的包
    在这里插入图片描述


  包的访问权限控制举例

如果在www这个包里面创建一个Test1类,类内部定义有 包访问权限的age,在不同包 demo包中创建一个Test2类,那么对于age来说 在不同包中Test2类就不能访问age,只能在demo这个包中被访问

在这里插入图片描述


在这里插入图片描述


二、static成员

成员变量分为 静态成员变量 和 实例成员变量

2.1static关键字的引入

  static修饰成员变量
以学生类进行举例,代码示例如下

public class Student{
   public String name;
   public String sex;
   public int age;
   
   public Student(String name,String sex,int age) {
      this.name = name;
      this.sex = sex;
      this.age = age;
   }
public static void main (String[] args) {
   Student stu1 = new Student ("张三","男",18);
   Student stu2 = new Student ("李四","男",19);
}
}

Student类创建两个学生对象,那么如果这两个学生都在同一个教室403上课,或者有100个学生对象都在403教室上课,是不是要再加入一个public修饰的classroom的成员变量,并且在每次实例化学生对象时,都要输入相同的教室403?如果有非常多的学生,这样会造成大量重复的输入,那么就体现了static关键字的作用了,我们只需定义一个静态成员变量classRoom,这个成员变量前用static进行修饰,说明这个变量是属于类的变量,不依赖于对象,是所有对象共享的,随类的加载而加载,生命周期随类的创建而被加载,随类的卸载而销毁。
代码示例如下

public class Student{
   public String name;
   public String sex;
   public int age;
   public static String classRoom = "403";//就地初始化
   public Student(String name,String sex,int age) {
      this.name = name;
      this.sex = sex;
      this.age = age;
   }
public static void main (String[] args) {
   Student stu1 = new Student ("张三","男",18);
   Student stu2 = new Student ("李四","男",19);
}
}

2.2静态成员变量初始化

注意:静态成员变量一般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性

  1. 就地初始化:在定义时,直接给出初始值
  2. 静态代码块初始化:下面会提及…

2.3访问静态成员变量

在其类外使用时需要用类名进行访问,但也可以用当前对象的引用进行访问,但是这种方法不合理。
使用类名访问,代码示例如下

Student.classRoom = 306System.out.println(Student.classRoom);

2.4用实际问题加深静态成员变量的理解

  1. 阅读以下代码,变量count的最终值为多少?
class TestStatic {
  public static int count = 10;
  public static void main(String[] args) {
     TestStatic testStatic1 = new TestStatic();
     testStatic1.count++;
     
     TestStatic testStatic2 = new TestStatic();
     testStatic2.count++;
     
     TestStatic testStatic2 = new TestStatic();
     testStatic2.count++;
     
     TestStatic.count--;
     
     System.out.println(count);
  }
}

count的最终值为12,countstatic修饰,说明count为静态成员变量,属于类的变量,不管实例化多少个对象,count也只有独一份,而这一份是随第一次类的加载而创建的,随后对count的多次操作,都是针对这唯一一个count操作的。


  1. 阅读以下代码,变量age是否能被打印,打印的数是多少?为什么?
class Person {
   public static int age;
}

public class Test{
   public static void main(String[] args) {
      Person person = null;
      System.out.println(person.age);
   }
}

能被打印,打印的值为10,;age是静态成员变量,不依赖于对象,属于类的变量;Person person = null说明person引用不指向任何的对象,而age本身就独立于对象,所以访问ageperson引用所指的对象为不为空 没有关系,因为age是类的变量,不在对象里

2.5静态成员变量的总结要点

  1. static修饰的成员变量属于类的变量,储存在方法区中,随类的加载而被加载,不再属于对象,不再依赖于对象。
  2. 静态成员变量不属于某个对象,是类的属性,是多个对象共享的,即使创建多个对象也不会新增第二个静态成员变量。
  3. 在其类外使用时需要用类名进行访问,但也可以用当前对象的引用进行访问,但是这种方法不合理。
  4. 生命周期伴随类的一生:随类的加载而创建,随类的卸载而销毁。(当用类名进行访问类的属性时,类就会被加载,进而这些静态成员变量就会被创建)
  5. 方法中不能定义和使用静态成员变量,在方法当中定义的变量是局部变量,而静态的变量属于类变量。随着类的加载而被创建,而局部变量是调用该方法的时候,才创建的。所以,此时两种变量的性质是冲突的。Java当中不允许定义局部的静态变量

  static修饰成员方法
Java中,被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。静态成员一般是通过
静态方法来访问的。代码示例如下:

public class Student{
  // ...
  private static String classRoom = "306";
  // ...
  public static String getClassRoom(){
    return classRoom;
  }
}
  public class TestStudent {
    public static void main(String[] args) {
    System.out.println(Student.getClassRoom());
  }
}

输出:306


2.6静态成员方法的总结要点

  1. 静态成员方法不属于某个具体的对象,属于类的方法。
  2. 要用类名的方式调用,也可以用当前对象的引用进行调用,但是这样调用不合理
  3. 静态成员方法里面不能任何访问非静态的成员变量或成员方法,也不能出现this参数,因为这些都是依赖于对象的,而静态成员方法属于类的方法,不依赖于对象

三、代码块

代码块用来初始化成员变量,
实例(构造)代码块:一般用来初始化实例成员变量(非静态成员变量)
静态代码块:一般用来初始化静态成员变量


3.1普通代码块

定义在方法中的代码块,使用{ }定义,代码示例如下:

public class Main{
  public static void main(String[] args) {
{ //直接使用{}定义,普通方法块
    int x = 10 ;
    System.out.println("x1 = " +x);
} 
   int x = 100 ;
   System.out.println("x2 = " +x);
}
}

运行结果:x1 = 10
x2 = 100

这种用法比较少见


3.2构造代码块

也叫实例代码块,一般用来初始化实例成员变量(非静态成员变量);定义在类的里面,方法的外面,
使用{}定义,代码示例如下:

public class Student{
   public String name;
   public int age;
   public static String classRoom = "403";//就地初始化
   public Student(String name,int age) {
      System.out.println("构造方法");
      this.name = name;
      this.age = age;
   }
   
   {
      age = 16;
      System.out.println("构造代码块");
      
    }

public static void main (String[] args) {
   Student stu1 = new Student ("张三",18);
   System.out.println(stu1.age);
}
}

运行结果:
构造代码块
构造方法
18

运行结果说明,先执行构造代码块,后执行构造方法


3.3静态代码块

一般用来初始化静态成员变量;定义在类的里面,方法的外面,
使用static {}定义,代码示例如下:

public class Student{
   public String name;
   public int age;
   public static String classRoom = "403";//就地初始化
   public Student(String name,int age) {
      System.out.println("构造方法");
      this.name = name;
      this.age = age;
   }
   
     
   {
      age = 16;
      System.out.println("构造代码块");
      
    }

   static {
   
      classRoom = "309";
      System.out.println("静态代码块");
      
    }

public static void main (String[] args) {
   Student stu1 = new Student ("张三",18);
   System.out.println(Student.classRoom);
}
}

运行结果:
静态代码块
构造代码块
构造方法
309

运行结果说明,执行顺序:静态代码块 > 构造代码块 > 构造方法
另外若有多个静态代码块,执行顺序按照定义代码的先后顺序执行,且静态代码块只会被执行一次


3.4代码块的总结要点

  • 静态代码块不管生成多少个对象,其只会执行一次
  • 静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的
  • 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(合并)
  • 实例代码块只有在创建(new)对象时才会执行,只通过类名访问静态成员时,不会被执行
  • 执行顺序:静态代码块 > 构造代码块 > 构造方法


原文地址:https://blog.csdn.net/2401_83147199/article/details/142108913

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!