在Java中,包是一种用于组织和管理类,接口和其他包的机制。主要作用是防止命名冲突,并提供一种访问控制机制

package关键字的主要作用是声明当前类在哪个包里面。 当然,用户也可以自定义包,在自定义的包中编写用户自己的代码。不过,自定义包的时候应该遵循以下规范
在Java中,JDK已经提供了很多现成的类供我们使用,如果我们要使用就有两种方式
(1)使用类的全限定名:包名+类名(一般不推荐)

(2)先导入包,再使用类名(常见用法)


这段代码的作用是:将java.util包(文件夹)下面的Arrays类导入到当前的java文件中,当用户需要使用Arrays时,编译器就会根据该代码的路径去定位Arrays类,这就体现了包的访问控制机制 如果需要使用java.util包里的其他类,可以这么导入
import java.util.*;星号的意思不是导入java.util包里的全部类,而是当我们需要使用java.util里的某类时,根据这个路径去定位目标类
注意:

Date类在javautil和java.sql包中都有,如果使用星号来导入类,就无法区分使用哪个包中的Date类,解决办法如下:
Java中的访问限定修饰符一共有四个:public,protected,default和private。主要用于控制类、方法和变量的可见性和访问权限
如果没有使用任何访问限定修饰符,就是default(包私有)访问权限
修饰类时:

修饰成员变量/方法时:


被public声明的类/变量/方法都可以被任意的其他类访问,无论它们是否在同一包里 修饰类时:

修饰成员变量/方法时:

封装是面相对象编程的三大基本特性之一(其他两个是继承和多态,后面的博文再介绍),指的是将类的数据(属性)和操作数据的方法绑定在一起,并对外隐藏内部实现的具体细节,仅提供必要的接口与外界交互。以电脑为例,电脑对外提供的接口就只是:开关机、通过键盘输入,显示器,USB插孔等,用户使用这些设备和电脑进行交互,完成日常事务

对于使用电脑的我们而言,只需要知道鼠标、键盘、开关机键等设备怎么使用就行了,至于为什么按了开机键电脑能亮起来,这个我们就不需要关心了。而要实现封装,就离不开private修饰符
使用private修饰的成员变量/方法只能在定义它们的类中访问,在外部类中一般是不能访问的(这里不考虑反射)

如果要访问使用private修饰的成员变量,可以对外提供一个get和set方法作为公开的接口,代码实现如下:
public class MyDate {
private String year;
private String month;
private String day;
/*//
public MyDate() {
this("2025","5","1");
}
public MyDate(String year, String month, String day) {
this.year = year;
this.month = month;
this.day = day;
}*/
//
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
public String getMonth() {
return month;
}
public void setMonth(String month) {
this.month = month;
}
public String getDay() {
return day;
}
public void setDay(String day) {
this.day = day;
}
}
class Test{
public static void main(String[] args) {
MyDate myDate = new MyDate();
//使用get方法获取private修饰的成员变量
System.out.println(myDate.getYear());
System.out.println(myDate.getMonth());
System.out.println(myDate.getDay());
//使用set方法修改private修饰的成员变量
myDate.setYear("2025");
myDate.setMonth("5");
myDate.setDay("1");
//使用get方法获取private修饰的成员变量
System.out.println(myDate.getYear());
System.out.println(myDate.getMonth());
System.out.println(myDate.getDay());
}
}运行结果如下:

注意:
static可以修饰成员变量/方法,至于static有什么用,这里先举个例子看看不适用static和使用static修饰的区别

static修饰的成员变量,称为静态成员变量,静态成员变量最大的特性:不属于某个具体的对象,是所
有对象所共享的。当classroom不使用static修饰时,classroom变量存储在对象内部;当classroom使用static修饰时,classroom变量没有存储在对象内部。这是因为static成员属于类本身,而不属于某个对象,在整个内存中只存在一份副本,被所有对象共享,存储在方法区中。
以上面的代码为例,假如实例化的所有学生对象都属于同一个班的学生,当classroom不不使用static修饰时,每个对象内部都会保存一份classroom成员变量;当使用static修饰后,classroom变量不依附于对象而存在,存储在方法区中,被所有的学生对象共享。使用static修饰后的直接好处是,classroom变量在内存中只有一份,而不需要保存多份
静态/类变量特性:
在Java中,使用static修饰的方法称为静态方法,是类的方法,不属于某个对象
public class Student {
public String name;
public int age;
//静态成员变量
public static String classroom;
//构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//静态方法
public static String getClassroom(){
return classroom;
}
}静态方法的特性:

因为在调用非静态成员变量/方法时,会使用this引用,但是静态方法不属于某个对象,无法传递this引用。如果需要在静态方法中访问非静态成员变量/方法,只能通过对象来访问
public class Student {
public String name;
public int age;
//静态成员变量
public static String classroom;
//构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//
public void print(){
System.out.println(name + " " + age);
}
//静态方法
public static String getClassroom(){
//实例化对象
Student student = new Student("王五",20);
return student.name;
}
}静态成员变量一般不适用构造方法来初始化,因为构造方法是给某个对象来初始化变量,而静态变量是类的变量,被所有对象共享。所有静态成员变量的初始化分为:就地初始化和静态代码块初始化
在定义变量的时候指定初始值
public static String classroom = "100";那么接下来就要介绍什么是代码块了
使用{}包围起来的代码就叫做代码块,根据代码块定义的位置和使用的关键字可分为四种
普通代码块:在方法中定义的代码块
public class demo1 {
public static void main(String[] args) {
{
int a = 1;
System.out.println("a = " + a);
}
int a = 2;
System.out.println("a = " + a);
}
}运行结果: a = 1 a = 2
构造/实例代码块:在类中定义的代码块,一般用于初始化非静态成员变量
public class Student {
public String name;
public int age;
//构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//
public void print(){
System.out.println(name + " " + age);
}
//构造/实例代码块
{
this.name = "八戒";
this.age = 1000;
}
}
class Test{
public static void main(String[] args) {
Student student1 = new Student("张三",18);
student1.print();
}
}运行结果: 张三 18
根据运行结果可以判断出,实例代码块的执行时间比构造方法早(和定义的位置无关,因为上述代码中构造方法定义在前,但仍然是实例代码块先执行)
注意:如果非静态成员变量有就地初始化操作,此时实例代码块和非静态成员变量谁先赋值就取决于它们定义的位置关系

public class Student {
public String name;
public int age;
//静态成员变量
public static String classroom;
//构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//静态代码块
static {
classroom = "100";
System.out.println("静态代码块执行");
}
}
class Test{
public static void main(String[] args) {
Student student1 = new Student("张三",18);
Student student2 = new Student("李四",19);
System.out.println("classroom = " + Student.classroom);
}
}执行结果: 静态代码块执行 classroom = 100
注意:
public class Student {
public String name;
public int age;
//静态代码块1
static {
classroom = "100";
System.out.println("静态代码块1执行");
}
//静态代码块2
static {
classroom = "200";
System.out.println("静态代码块2执行");
}
//静态成员变量
public static String classroom = "300";
//构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
class Test{
public static void main(String[] args) {
Student student1 = new Student("张三",18);
Student student2 = new Student("李四",19);
System.out.println("classroom = " + Student.classroom);
}
}执行结果: 静态代码块1执行 静态代码块2执行 classroom = 300
使用synchronized修饰的代码块,主要和多线程有关,这里不再详细讲解,我以前的博客中讲过