Java对象基础, since 2021-08-15

(2021.08.15 Sun)

创建对象

假定一个类的名字为demoClass,则创建该类一个对象的语法如下

demoClass a = new demoClass();

String类与其他类型不同,可将字面量赋给它,如同基本数据类型一样,而这种赋值方法仅适用于String类和其他表示基本数据类型的类,如IntegerDouble

String a = "adfasdf"
Float b = 12.6F

对象创建过程

使用运算符new创建对象时,依次发生如下几件事:

  • 创建给定类的实例(instance)
  • 为实例分配内存
  • 调用给定类的构造函数,构造函数用于初始化新对象及其变量,创建该对象所需的其他对象,并执行初始化该对象所需的其他操作

同一个类中可以有多个构造函数,每个构造函数的参数类型和数目不同。使用new时,可以在参数列表中指定不同的参数,这将调用响应的构造函数。如果类中没有定义构造函数,创建对象时,默认将调用没有参数的构造函数,其作用是调用超类中不接收任何参数的构造函数。

内存管理和引用

与Python相似,Java中的内存管理是动态和自动的,并且不需要使用者特别关心。创建对象时分配内存的任务由Java虚拟机(VM)完成。对象使用完成后,Java能够判断出该对象已经不再有任何活动的引用(即该对象没有被赋给任何正在使用的变量或被存储在数组中)。

动态垃圾回收:Java VM定期检查未用的对象,并收回这些对象占用的内存。

将对象赋给变量或其他作为参数传递给方法时,实际上没有使用对象,只是对对象的引用。对对象的引用实际上是指针。

比较对象时,可比较两个对象的名字是否是(指向)同一个对象(用==),也可比较两个对象的值是否相同(用String.equals())。

class testClass {
    public static void main(String[] arguments) {
        String a, b, c;
        a = 'asdf';
        b = a;
        c = "asdf";
        System.out.println("a and b the same object: " + (a==b)); // true
        System.out.println("a and c the same object: " + (a==c)); // false
        System.out.println("a and c the same value: " + (a.equals(c))); // true
}

类变量和实例变量

类变量适用于类和所有实例。类变量只有一个copy,修改它的值将改变所有实例。类变量在类中定义时,前面加关键字static

class familyMember {
    static String surname = "James";
    String giverName;
    int = age;
}

调用类变量时直接引用类名和类变量名即可

System.out.println(familyMember.surname);

对类变量的修改将影响该类的所有对象。

实例变量可在初始化时赋值,引用实例变量需要指定实例的名字,而非类名。

familyMember a = new familyMember;
a.givenName = "Clarke";
a.age = 38;
System.out.println("age: "+ a.age);

对象和基本数据类型的强制类型转换(casting)

强制转换基本数据类型

一个基本原则是目标类型应该比源类型保存更大的值。譬如,byte类型范围是-128~127,可强制转换为short类型,而反过来则不行。由于更大范围的类型比更小范围类型的精确度高,所以不会导致信息丢失。一个例外是整数转换为浮点数,long float/double时,都将导致精度降低。
可能的转换顺序:
byte/char int float/long double
转换的格式如下

// (tpename) value
float a = 9.0;
int b = (int) (a); // (int) a;

强制转换对象

必须满足条件:源类和目标类之间存在继承关系,即其中的一个是另一个的子类。子类有着比超类更多的方法和属性。要在需要子类对象的地方使用超类对象,需要进行显式的强制类型转换。在转换过程中,不会损失任何信息,而得到了子类定义的全部方法和变量。

在下面案例中,VicePresidentEmployee的子类,包含更多信息。

// (classname) object
Employee emp = new Employee();
VicePresident veep = new VicePresident();
emp = veep;
veep = (VicePresident) emp;
对象与类的关系判断

判断一个对象所属的类,或该对象是否属于某个类。

  • 方法1:在Object类中定义了一个方法getClass,所有Java对象都包含它,这个方法返回一个Class对象,指出了对象所属的类,对象的getName方法返回一个表示类名的字符串。
// define an instance kk
String name = kk.getClass().getName();
  • 方法2:instanceof运算符,该运算符操作两个部分,左为对象的引用,右为类名,返回一个boolean
boolean check 1 = "Shanghai" instanceof String;

基本类型和对象之间的转换

java.lang包中包含了对应于每种基本数据类型的类:FloatBooleanByte等,这些类的大多与数据类型的名称相同,只是类名首字母大写,即Short而非short。另外,有两个类的名称与对应的数据类型不同,即char-Characterint-Integer

每个基本类型对应的类,可以创建存储相同值的对象。

Integer dataCount = new Integer(11);
int newCount = dataCount.intValue();

将字符串转换成数字类型比如int时,可用Integer的内置方法parseInt()

String penn = '65535';
int pen = Integer.parseInt(penn);

通过自动封装(autoboxing)拆封(unboxing),这两个自动转换过程,处理表示同一类值的基本类型和对象时更为容易。

Float f1 = 12.5F;
Float f2 = 27.2F;
System.out.println('lower number: " + Math.min(f1, f2));

这里的f1f2都是对象,而Math.min方法接收float参数却被传递了对象。编译器将Float对象拆封为float值,再将其传递给Math.min方法。

对字符串的分割

对字符串的分割使用java.util中的StringTokenizer类。

import java.util.StringTokenizer
class TokenTest {
    public static void main(String[] arguments) {
        String a = "asdf 33242 3.4";
        String b = "asdf@fadf@123";
        StringTokenizer t1, t2;
        t1 = new StringTokenizer(a);
        System.out.println("part 1: "+t1.nextToken());
        System.out.println("part 2: "+t1.nextToken());
        System.out.println("part 1: "+t1.nextToken());
        t2 = new StringTokenizer(b, '@');
        System.out.println("part 1: "+t2.nextToken());
        System.out.println("part 2: "+t2.nextToken());
        System.out.println("part 1: "+t2.nextToken());
    }
}

Reference

1 R. Cadenhead著,袁国忠译,21天学通Java(第7版),中国工信出版集团,人民邮电出版社

你可能感兴趣的:(Java对象基础, since 2021-08-15)