Java中的所有东西都是对象。对象是类的一个实例,当创建一个类时,对象就是该类的一个实例化实体。在Java中,每个对象都有状态和行为,其状态由属性领域存储,行为由方法领域定义。
一、对象的创建与使用
Java中对象的创建需要两步:声明对象,实例化对象。
public class Car { String brand;//属性领域 int price;//属性领域 public void run() { System.out.println("开车啦!");//方法领域 } } public class Test { public static void main(String[] args) { Car car = new Car();//声明并实例化一个Car对象 car.brand = "BMW";//给对象car设置属性 car.price = 1000000; car.run();//对象执行方法 } }
创建对象后,可以使用对象的属性和方法,如上面代码中通过对象car的访问运算符"."来设置和访问对象的属性和方法。
二、对象的初始化
当创建一个对象时,该对象的属性都有初始值。如果没有显示地为属性赋值,则会自动赋予其初始值。
Java中的默认值:
- byte,short,int,long的默认值为0
- float,double的默认值为0.0
- char的默认值为'\u0000'
- boolean的默认值为false
- 其他类型的默认值为null
三、对象的访问控制
Java提供了4种访问修饰符控制对象的访问权限:
- public:公共访问级别
- protected:受保护的访问级别
- default:(缺省)的访问级别
- private:私有访问级别
访问修饰符可以用于修饰类、属性、方法等。以下代码演示了使用访问修饰符来限制对象的访问权限。
public class Person { public int age;//公共访问级别 protected String name;//受保护的访问级别 String sex;//(缺省)的访问级别 private String id;//私有访问级别 //构造方法 public Person(int a, String n, String s, String i) { this.age = a; this.name = n; this.sex = s; this.id = i; } //公共方法 public void display() { System.out.println("姓名:" + this.name + ",性别:" + this.sex + ",年龄:" + this.age + ",身份证号:" + this.id); } } public class Test { public static void main(String[] args) { Person person = new Person(20, "张三", "男", "100010200001012345");//声明并实例化一个Person对象 person.display();//调用对象的display方法 System.out.println(person.name);//访问对象的受保护属性 System.out.println(person.sex);//访问对象的(缺省)属性 // System.out.println(person.id); //对象的私有属性无法访问 } }
四、对象的比较
在Java中,可以使用“==”和“equals()”两种方式比较对象。
“==”比较的是对象的内存地址,而“equals()”比较的是对象的内容。
public class Student { String name; int age; //构造方法 public Student(String n, int a) { this.name = n; this.age = a; } @Override public boolean equals(Object obj) { if (obj instanceof Student) { Student s = (Student) obj; if (this.name.equals(s.name) && this.age == s.age) { return true; } } return false; } } public class Test { public static void main(String[] args) { Student s1 = new Student("张三", 20); Student s2 = new Student("张三", 20); Student s3 = s2; System.out.println(s1 == s2);//比较的是对象的内存地址 System.out.println(s1.equals(s2));//比较的是对象的内容 System.out.println(s2 == s3);//比较的是对象的内存地址 } }
五、对象的垃圾回收
在Java中,对象的内存空间是由Java虚拟机管理的。Java虚拟机通过垃圾回收算法自动回收那些不再被任何对象引用的内存空间。
Java中的垃圾回收策略有两种:
- 标记-清除算法
- 引用计数算法
在现代JVM中,一般采用标记-清除算法,并且结合其他回收算法来提高回收效率。示例代码如下:
public class Test { public static void main(String[] args) { for (int i = 0; i < 1000; i++) { new Person(i, "person" + i);//创建大量的对象 } } } class Person { public int age; public Person(int age, String name) { this.age = age; } // final 方法可以重载,因为它是隐式的局部变量 @Override protected void finalize() throws Throwable { System.out.println("Person对象被回收了"); } }
使用finalize方法,在对象被垃圾回收前进行必要的资源释放。
六、对象的序列化和反序列化
Java对象在网络传输或者保存至硬盘时需要经过序列化操作。Java的序列化机制就是将对象转化为二进制流,序列化操作的结果是一个byte数组。通过将序列化后的byte数组进行后续操作,可以实现将对象存储在磁盘上,或在网络上传输,最终再将byte数组转化为对象。
public class Address implements Serializable { private Integer id; private String name; public Address(Integer id, String name) { this.id = id; this.name = name; } // getter 和 setter 方法 @Override public String toString() { return "Address{" + "id=" + id + ", name='" + name + '\'' + '}'; } } public class User implements Serializable { private Integer id; private String name; private List addresses; public User(Integer id, String name, List addresses) { this.id = id; this.name = name; this.addresses = addresses; } // getter 和 setter 方法 @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", addresses=" + addresses + '}'; } } public class SerializeDemo { public static void main(String[] args) throws Exception { List addresses = new ArrayList(); addresses.add(new Address(1, "北京海淀")); addresses.add(new Address(2, "北京朝阳")); User user = new User(1, "张三", addresses); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("user.obj"))); oos.writeObject(user); oos.flush(); oos.close(); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("user.obj"))); User u = (User) ois.readObject(); ois.close(); System.out.println(u); } }
上述代码中,Address和User对象都实现了Serializable接口,表示这个类可以以序列化的方式进行存储和传输操作。通过ObjectOutputStream将对象序列化成byte数组,通过ObjectInputStream将byte数组转化成对应的对象。