包(Package)就像我们电脑中的文件夹一样,通过将不同类型的文件放在不同不同的文件中,来达到方便管理和查找的作用.在java中,包的作用就是用来组织各个类,这样不仅方便管理,还能有效防止类名冲突.
如上段话所说.主要作用是方便管理和防止类名冲突.
例如:虽然一个项目中两个不同的程序员都写了一个名为Add类,但是一个放在add1包中,另一个放在add2包中便不会报错
java中使用包的方法是直接进行导入即可,但导入的包必须先声明
java中提供了关键字package来进行声明包操作
package demo1; //声明包
public class Add {
public static int add(int a, int b)
return a + b;
}
java中提供了关键字import来进行导入包操作
import demon1.Add; //导入包
public class Test { //类定义不能用static
public static void main(String[] args){
int sum = Add.add(1, 2); //使用包
System.out.println(sum);
}
}
另外,还有一种使用包的方式,该方式无需导入,如下
public class Test {
public static void main(String[] args) {
int sum = demo1.Add.add(1,2);
System.out.println(sum);
}
}
当两个不同的包中有同一个名字的类
import java.util.Date;
import java.sql.Date;
public class aa {
public static void main(String[] args) {
Date date = new Date();
}
}
如果我们试图将这两个类都导入会报错,毕竟IDE也不知道你究竟是用哪个包的类
这个时候,我们可以用显式导入,指定Dete类使用的包,便不会报错
import java.util.Date;
import java.sql.Date;
public class aa {
public static void main(String[] args) {
java.util.Date date = new java.util.Date();
}
}
方式 | 示例 | 优点 | 缺点 |
---|---|---|---|
导入具体类 | import demo1.Add; | 明确依赖,可读性好 | 需逐个导入 |
导入包下所有类 | import demo1.*; | 方便,少写代码 | 可能引入多余类 |
显式导入 | demo1.Add.add(1,2); | 无需导入 | 代码冗长 |
封装(Encapsulation)是 Java 面向对象编程的三大特性之一(另外两个是继承和多态),它就像是把东西包装在一个盒子里,只留几个 “接口” 让外部使用,而隐藏内部的具体实现.
假如对于一个空调,它能做的事情只有开关机,制热,制冷.而对于用户来说,用户不需要知道是怎么做到开关机,制冷,制热的.用户只需要知道怎么来让空调开关机,制热,制冷即可.
class Animal {
//实例变量
private String name;//使用private修饰
private int age;
private String type;
//实例方法
public void eat() {
System.out.println(name + "在吃饭");
}
public void play() {
System.out.println(name + "在玩耍");
}
}
public class Test {
public static void main(String[] args) {
Animal animal1 = new Animal();
}
}
这个代码便完成了封装操作.和之前的代码对比,感觉变化不是很大对吧.只是把每一个变量和方法都用private修饰了.而这正是封装的关键,private修饰的变量和方法都变成了"私有的",这时候只有在这个Animal类中的代码才可以调用和修改修饰后的变量和方法.但我们可以通过接口来进行修改private修饰的值
// 在Test类的main方法中补充调用示例
public class Test {
public static void main(String[] args) {
Animal animal1 = new Animal();
animal1.setName("小狗"); // 通过setter设置属性
animal1.setAge(3);
System.out.println(animal1.getName()); // 通过getter获取属性
animal1.eat(); // 调用公有方法
}
}
class Animal {
//实例变量
private String name;//使用private修饰
private int age;
private String type;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
//实例方法
public void eat() {
System.out.println(name + "在吃饭");
}
public void play() {
System.out.println(name + "在玩耍");
}
}
public class Test {
public static void main(String[] args) {
Animal animal1 = new Animal();
}
}
增强 getter/setter 的示例
public void setAge(int age) {
if (age < 0 || age > 100) { // 添加参数校验
System.out.println("年龄不合法!");
return;
}
this.age = age;
}
这个时候我们即使代码不在该类中也可以通过留下的特定接口来获取和修改private修饰的值了
在 Java 里,访问限定符(也叫访问修饰符)是实现封装的关键工具,它们就像是给类、属性、方法设置的 “门禁系统”,控制着谁能访问这些代码。
一共有四个
限定符 | 全局 | 子类 | 同一个包 | 类内部 |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | × | √ | √ | √ |
default | × | × | √ | √ |
private | × | × | × | √ |
static 是 Java 中的一个关键字,用于修饰类、方法、变量或代码块。它的核心作用是让被修饰的成员属于类本身,而不是类的某个对象.被static修饰的成员,称为静态成员,也可以称为类成员,它不属于某个具体的对象,是所有对象共享的.
假如我们定义一个学生(Student)类,然后里面有三个同班级的学生.我给的定义属性是名字,年龄,班级.那么我们可以很简单的想到如下的定义
package demo1;
class Student {
private String name;
private int age;
public String classroom;
}
public class Test {
public static void main(String[] args) {
Student stu1 = new Student();
Student stu2 = new Student();
Student stu3 = new Student();
}
}
初看感觉没什么大问题,但细看还是有一个可以优化的点.就是以这个定义来new对象的话,我们每new一个都得重新设置一个班级,即使这三个学生班级相同.如果想保证这三个同学都默认是一个班级,那么我们用static修饰一下classroom使其变为类成员即可
package demo1;
class Student {
private String name;
private int age;
static String classroom;
}
public class Test {
public static void main(String[] args) {
Student stu1 = new Student();
Student stu2 = new Student();
Student stu3 = new Student();
}
}
这个时候再new的对象就默认了classroom是同一个.原因就是因为static修饰的成员会变成类成员(静态成员).此时它已不属于某个具体的对象,是所有对象共享的.
static修饰的变量会在该类被加载时默认一同加载(无论有没有其它对象使用)
static修饰的变量既可以通过类直接访问,也可以通过对象来间接访问
package demo1;
class Student {
private String name;
private int age;
static String classroom = "软件工程2401班";
}
public class Test {
public static void main(String[] args) {
Student stu1 = new Student();
System.out.println(Student.classroom);//通过类名直接访问
System.out.println(stu1.classroom);//通过对象访问
}
}
被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的.静态成员一般是通过静态方法来访问的.
package demo1;
class Student {
private String name;
private int age;
public static String classroom = "软件工程2401班";
public static String getClassroom() {
return classroom;
}
}
public class Test {
public static void main(String[] args) {
Student stu1 = new Student();
System.out.println(Student.getClassroom());
}
}
静态方法可以调用静态方法,但不能直接调用非静态方法(需要先创建对象),因为非静态方法没有伴随类的加载而加载,
静态方法不能使用this或super关键字,因为他们指向对象实例
注意:静态成员变量⼀般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性.
静态成员变量的初始化分为两种:就地初始化和静态代码块初始化
在定义时直接给出初始值
public class Student{
private String name;
private String gender;
private int age;
private double score;
private static String classRoom = "1-101";
}
public class School {
static String schoolName;
static int studentCount;
static { // 静态代码块
schoolName = "XX中学";
studentCount = 1000;
System.out.println("学校初始化完成");
}
}
使用import static
关键字来用于导入静态方法或变量,避免重复写类名
import static java.lang.Math.sqrt; // 导入静态方法
public class Calc {
public static void main(String[] args) {
double result = sqrt(16); // 直接调用sqrt(),无需Math.sqrt()
}
}