【Java SE】类和对象(二)
本节目标理解包package的作用掌握导入类、自定义包、常用系统包理解面向对象三大特性之封装掌握四种访问权限修饰符、get/set 方法深度掌握static关键字静态成员变量、静态成员方法分清实例与静态的区别掌握四种代码块普通代码块、实例构造代码块、静态代码块熟悉执行顺序1. 包 package1.1 什么是包包是 Java 组织管理类的一种机制类似电脑文件夹目录。 作用解决类名冲突不同包下面可以有相同名字的类不会冲突。分类管理大量的类提高代码可读性项目结构清晰。类比电脑磁盘文件夹把 C 语言作业、Java 作业、数据结构作业分不同文件夹存放。Java 使用包对类、接口进行分层组织。1.2 使用包里面已有的类import 导入Java JDK 自带大量已经写好的类例如java.util.Date时间类。方式 1写完整全限定类名不推荐写起来冗长public class Test { public static void main(String[] args) { // 完整包名类名 java.util.Date date new java.util.Date(); System.out.println(date.getTime()); } }方式 2import 包名.类名;显式导入指定类推荐import java.util.Date; public class Test { public static void main(String[] args) { Date date new Date(); System.out.println(date.getTime()); } }方式 3通配符导入import java.util.*;*代表导入该包下所有类。import java.util.*; public class Test { public static void main(String[] args) { Date date new Date(); System.out.println(date.getTime()); } }⚠️通配符缺点如果两个不同包存在同名类会出现类名歧义编译报错。冲突案例java.util.Date和java.sql.Date两个包都有 Date 类。import java.util.*; import java.sql.*; public class Test { public static void main(String[] args) { // 编译报错分不清是util的Date还是sql的Date // Date date new Date(); // 出现冲突时写完整全限定类名 java.util.Date date new java.util.Date(); System.out.println(date.getTime()); } }静态导入import static导入类里面静态的字段、静态方法调用的时候不需要写类名。import static java.lang.Math.*; public class Test { public static void main(String[] args) { double x 30; double y 40; // 原本写法 Math.sqrt(Math.pow(x,2)Math.pow(y,2)); double result sqrt(pow(x, 2) pow(y, 2)); System.out.println(result); } }1.3 自定义包1.3.1 自定义包语法规则在.java源文件最顶部写package 包名;必须放在所有 import 之前。包名习惯使用公司域名颠倒例如com.bit.demo1全部小写不要大写。包名和磁盘文件目录严格对应com.bit.demo1对应文件夹路径com/bit/demo1/。如果文件没有写package该类属于默认无名包不适合正式项目。package com.bit.demo1; public class Test { public static void main(String[] args) { } }1.3.2 IDEA 创建包操作步骤1.在src目录右键 →New→Package2.输入包名com.bit.demo1IDEA 会自动创建多级文件夹。3.在包上面右键 →New→Class输入类名。4.生成的代码第一行自动生成package com.bit.demo1;。1.3.3 Java 常用系统包表格包名用途java.lang核心基础类String、Object、包装类自动导入不需要写 importjava.lang.reflect反射相关 APIjava.net网络编程 Socketjava.sql数据库 JDBC 编程java.util工具包集合 ArrayList、Scanner、日期工具开发高频java.io文件 IO 输入输出流1.4 包访问权限default 默认权限类、成员变量、方法不写任何访问修饰符就是包访问权限default。 ✅同一个包里面的类可以访问不同包完全不能访问。示例com.bit.demo1包下 Computer 类package com.bit.demo1; public class Computer { private String cpu; private String memory; public String screen; // default包访问权限不加修饰符 String brand; public Computer(String brand, String cpu, String memory, String screen) { this.brand brand; this.cpu cpu; this.memory memory; this.screen screen; } public void Boot(){ System.out.println(开机~~~); } }com.bit.demo2不同包访问 Computerpackage com.bit.demo2; import com.bit.demo1.Computer; public class TestComputer { public static void main(String[] args) { Computer p new Computer(HW, i7, 8G, 13*14); System.out.println(p.screen); // public可以访问 // System.out.println(p.cpu); // ❌private本类之外不能访问 // System.out.println(p.brand); // ❌default包访问跨包不能访问 } }2. 封装面向对象三大特性封装、继承、多态本章节重点学习封装。2.1 封装概念封装把数据成员变量和操作数据的方法包装到类当中隐藏内部实现细节只对外暴露安全的公共接口。生活类比笔记本电脑 电脑主板、CPU 内部复杂电路全部被外壳封装隐藏用户不需要懂电路只使用开机、键盘、USB 这些对外接口。内部零件改动不影响用户使用。代码实现封装成员变量使用private私有修饰类外部不能直接访问。对外提供getXxx()获取值、setXxx()设置值公共方法作为访问数据的唯一接口。基础版本未封装外部可以直接随意修改成员class Student{ private String name; private int age; public void eat() { System.out.println(this.name 正在吃饭!); } public void show() { System.out.println(name: name 年龄:age); } }提供 get/set 对外访问接口class Student{ //私有外部类不能直接访问 private String name; private int age; //get 获取name public String getName() { return name; } //set 设置name public void setName(String name) { this.name name; } public int getAge() { return age; } public void setAge(int age) { // 在set里面可以增加逻辑校验比如年龄不能负数 if(age 0 age 150){ this.age age; } } public void eat() { System.out.println(this.name 正在吃饭!); } public void show() { System.out.println(name: name 年龄:age); } } public class Test { public static void main(String[] args) { Student stu new Student(); stu.setAge(10); System.out.println(stu.getAge()); } }✨封装三大好处降低耦合类内部实现修改只要对外公共接口不变外部调用代码不需要改动。简化使用隐藏复杂内部细节使用者只调用公开接口不用关心内部实现。提高安全性可以在 set 方法做参数校验阻止外部随意篡改非法数据。2.2 四种访问权限修饰符表格修饰符本类内部同一个包子类 (不同包)其他包普通类private私有✅❌❌❌default(不写修饰符包访问)✅✅❌❌protected保护✅✅✅❌public公开✅✅✅✅说明private只允许当前类内部访问。default不加任何修饰包访问权限仅限同一个包。protected保护后续继承章节详细讲解。public任何地方都可以访问。开发编码习惯成员变量尽量private对外提供 get/set 公共接口。3. static 关键字static 可以修饰成员变量、成员方法。区分两个概念实例成员没有 static 修饰属于对象每个对象各自拥有一份。必须通过对象引用访问。static 静态成员类成员属于类所有对象共享一份存放在方法区。3.1 static 修饰成员变量静态成员变量场景多个学生都在同一个教室上课。教室不属于某一个学生全部学生共享同一个教室信息。如果写普通实例变量每个 new 出来 Student 对象都会单独存一份 classRoom内存浪费数据容易不一致。class Student{ private String name; private int age; public String classRoom; //实例变量每个对象单独一份 }使用 static 定义静态成员变量class Student{ private String name; private int age; //静态成员变量属于类所有对象共享 public static String classRoom 1‑101; }静态成员变量核心特性不属于某一个对象属于类所有对象共享同一份数据不在对象堆内存中存储。存储位置方法区。生命周期类加载的时候创建类卸载销毁生命周期比对象长。推荐使用类名.静态变量访问也可以对象引用访问不推荐。public class Test { public static void main(String[] args) { // ✅推荐类名直接访问静态成员 System.out.println(Student.classRoom); Student stu1 new Student(); Student stu2 new Student(); Student stu3 new Student(); // 不推荐虽然语法允许容易误导以为属于对象 System.out.println(stu1.classRoom); System.out.println(stu2.classRoom); System.out.println(stu3.classRoom); // 修改静态变量全部对象看到修改后的值 Student.classRoom 2‑202; } }3.2 static 修饰成员方法静态方法类方法public class Student{ private static String classRoom Bit306; //静态成员方法 public static String getClassRoom(){ return classRoom; } } public class TestStudent { public static void main(String[] args) { //推荐类名调用 System.out.println(Student.getClassRoom()); } }静态方法重要特性面试高频属于类不是对象的方法。推荐类名.方法()调用。❌静态方法里面不能直接访问实例成员变量非 static 成员。❌静态方法里面不能使用this关键字this 代表当前对象静态方法没有对象。❌静态方法不能直接调用普通实例成员方法实例方法依赖 this 对象。错误示例class Student{ private int age; private static String room; public static void func(){ // System.out.println(this.age); //编译报错静态没有this // age 10; //编译报错不能访问实例成员 // eat(); //编译报错不能直接调用实例方法 } public void eat(){ } }反过来普通实例成员方法可以访问静态成员变量、调用静态方法。实例方法有 this静态属于类全局存在。3.3 静态成员变量两种初始化方式就地初始化定义的时候直接赋值private static String classRoom 1‑101;静态代码块初始化适合复杂逻辑初始化。注意静态成员不要放到构造方法初始化构造方法是 new 对象的时候执行静态属于类加载阶段。4. 代码块使用{ }包裹的一段代码叫代码块一共 4 种普通代码块实例代码块构造代码块静态代码块同步代码块多线程后续讲解4.1 普通代码块写在方法内部的{}限定局部变量作用域。public class Main{ public static void main(String[] args) { { int x 10 ; System.out.println(x1 x); } // x 出了大括号作用域结束不能再使用 int x 100 ; System.out.println(x2 x); } }输出x1 10 x2 1004.2 实例代码块构造代码块写在类里面方法外面不加任何修饰符。作用用于初始化实例成员变量。 执行时机每次 new 对象实例化的时候执行在构造方法之前执行。public class Student{ private String name; private int age; private String gender; //实例代码块 { this.name bit; this.age 12; this.gender man; System.out.println(I am instance init()!); } public Student() { System.out.println(I am Student init()!); } public void show(){ System.out.println(name: name age: age sex: gender); } } public class Main { public static void main(String[] args) { Student stu new Student(); stu.show(); } }输出I am instance init()! I am Student init()! name: bit age: 12 sex: man每 new 一个对象实例代码块执行一次多个对象就执行多次。执行顺序实例代码块 → 构造方法。4.3 静态代码块使用static { }修饰写在类中方法外。用途专门初始化静态成员变量。 ⚠️执行时机类加载的时候执行无论 new 多少对象静态代码块只会执行唯一一次public class Student{ private String name; private int age; private static String classRoom; //实例代码块 { this.name bit; this.age 12; System.out.println(I am instance init()!); } //静态代码块 static { classRoom bit306; System.out.println(I am static init()!); } public Student(){ System.out.println(I am Student init()!); } } public static void main(String[] args) { Student s1 new Student(); Student s2 new Student(); }输出I am static init()! I am instance init()! I am Student init()! I am instance init()! I am Student init()!执行顺序总结类加载静态代码块最先执行只跑一次new 对象实例代码块执行 → 构造方法执行。如果类写多个静态代码块编译器会按照书写先后顺序合并执行。5. 课后习题选择题 1以下说法哪个是正确的 A. 在静态的成员方法当中可以使用非静态成员变量 B. 在静态的成员方法当中可以使用 this 关键字 C. 在非静态的成员方法当中可以使用静态成员变量 D. 静态的成员方法和静态的成员变量属于对象也就是在每个对象中都包含✅答案C解析 A静态方法不能访问实例成员。 B静态没有 this。 C实例方法可以访问静态成员正确。 Dstatic 属于类不属于对象。选择题 2关于 Java 中的封装以下哪个陈述是正确的 A. 封装要求所有类成员都必须被声明为 private。 B. 使用 public getter 和 setter 方法可以直接访问私有变量因此破坏了封装。 C. 封装允许在不影响使用类的代码的情况下修改类的内部实现。 D. 封装主要用于增加程序的运行速度。✅答案C解析 A不是全部成员必须 private。 Bget/set 正是封装对外提供的接口不会破坏封装。 C公共接口不变内部实现可以修改正确。 D封装和运行速度无关提升维护性安全性。本篇核心考点总结包 package管理类防止类名冲突import导入类import static静态导入java.util高频工具包。同名类冲突要写完整全限定名。封装隐藏内部细节成员 private对外提供 get/set 公共接口提高安全、降低耦合。访问权限private default包访问 protected public。static 静态静态成员属于类所有对象共享存放在方法区。推荐类名.静态访问。静态方法不能使用 this不能直接访问实例成员变量 / 实例方法实例方法可以访问静态。代码块普通代码块写在方法内限制局部变量作用域。实例代码块构造代码块new 对象执行先于构造方法每 new 一次执行一次初始化实例成员。静态代码块类加载执行只执行 1 次初始化静态成员。执行顺序静态代码块 (仅一次) → new 对象实例代码块 → 构造方法。面试简答Q静态代码块和实例代码块执行顺序A类加载执行静态代码块只执行一次每次 new 对象先执行实例代码块再执行构造方法。Q静态方法里面能不能用 this为什么A不能。this 代表当前对象引用静态方法属于类调用静态方法不一定需要创建对象。