首页 > 基础资料 博客日记

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

2024-09-20 08:00:06基础资料围观7

Java资料网推荐JavaSE语法阶段复习知识整理3之封装这篇文章给大家,欢迎收藏Java资料网享受知识的乐趣

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


一、封装

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
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!

标签:

相关文章

本站推荐

标签云