Java中的核心类

欢迎关注我的公众号【软件大爆炸】
Java学习中的碎碎念
Java中易忽略的基础知识
Java面向对象基础
Java中的核心类
Java抽象类和接口
Java中的异常
Java中的泛型与集合
Java为其8个基本数据类型提供了对应的封装类。基本类型对应的封装类除了 IntegerCharacter写法有点例外,其他的基本类型对应的封装类都是将首字母大写即可。

public class Test {
    public static void main(String[] args) {
        Integer objInt = new Integer(10);
        Character objChar = new Character('y');
        Float objFloat = new Float(89.87);
        byte num = 100;
        Byte objByte = new Byte(num);
        Long objLong = new Long(1000L);
        short num2 = 100;
        Short objShort = new Short(num2);
        Double objDouble = new Double(122.3d);
        boolean flag = false;
        Boolean objBoolean = new Boolean(flag);
    }
}

还可以通过传入一个数值字符串进行构造
例如

Integer objInt = new Integer("10");

等价于

Integer objInt = new Integer(10);

如果将对象赋值给基本数据类型则需要调用封装类的xxxValue()方法
例如:int num = objInt.intValue();

JDK1.5之后,Java提供了自动装箱(Autoboxing)和自动拆箱( Auto Unboxing)功能,因此,基本类型变量和封装类之间可以直接赋值。

装箱是指将基本类型数据值转换成对应的封装类对象,即将栈中的数据封装成对象存放到堆中的过程。
拆箱是装箱的反过程,是将封装的对象转换成基本类型数据值,即将堆中的数据值存放到栈中的过程。

public class Test {
    public static void main(String[] args) {
        Integer objInt = 10;
        int num = objInt;
    }
}

将字符串的值转换为基本类型的值有两种方式:

  • 直接利用封装类的构造方法,即Xxx( String s)构造方法;
int num = new Integer("100");
  • 调用封装类提供的 parseXxx( String s)静态方法
int num = Integer.parseInt("100");

将基本类型的值转换成字符串有三种方式:

  • 直接使用一个空字符串来连接数值即可
String str = ""+12;
  • 调用封装类提供的 tostring()静态方法
String num = Integer.toString(100);
  • 调用 String类提供的 valueof()静态方法
String num = String.valueOf(100);

关于Object.clone()方法
代码示例:

//第一个示例
class Student18 implements Cloneable{
    int rollno;
    String name;

    Student18(int rollno,String name){
        this.rollno=rollno;
        this.name=name;
    }

    public Object clone()throws CloneNotSupportedException{
        return super.clone();
    }

    public static void main(String args[]){
        try{
            Student18 s1=new Student18(101,"amit");

            Student18 s2=(Student18)s1.clone();

            System.out.println(s1.rollno+" "+s1.name);
            System.out.println(s2.rollno+" "+s2.name);

        }catch(CloneNotSupportedException c){}

    }
}
//第二个示例(与第一个没有关系)
Person p = new Person(23, "zhang");  
Person p1 = (Person) p.clone();  

System.out.println(p);  
System.out.println(p1);

clone()方法省去了创建对象精确副本的额外处理任务。 如果使用new关键字执行此操作,则将花费大量处理时间,这就是我们使用对象克隆的原因。

那么在java语言中,有两种方式创建对象:

  • 1.使用new操作符创建一个对象

详细步骤:分配内存空间,调用构造函数,初始化,构造方法返回

  • 2.使用clone方法复制一个对象

详细步骤:分配内存空间,调用clone()函数,使用原对象中对应的各个域填充新对象的域,clone方法返回。

很多朋友会对这两句代码产生疑问

Person p1 = new Person(1001,"xiaoming");
Person p2 = p1;//复制对象的第一种方式:直接采用地址赋值
Person p3 = (Person) p1.clone();//第二种方式:采用Object的clone()方法

下面是上面代码的完整版

public class Person implements Cloneable{
    private int id;
    private String name;

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        Person p1 = new Person(1001,"xiaoming");
        Person p2 = p1;//复制对象的第一种方式:直接采用地址赋值
        Person p3 = (Person) p1.clone();//第二种方式:采用Object的clone()方法
        System.out.println(p1);
        System.out.println(p2);
        System.out.println(p3);
    }
}

输出的结果如下:

club.BOOKJava8.Person@5fd0d5ae
club.BOOKJava8.Person@5fd0d5ae
club.BOOKJava8.Person@2d98a335

首先我们可以确定是,p1和p2是同一对象,他们的对象id相同。p2和p3并不是同一个对象,他们的对象id并不相同。
我用内存图来展示一下:
首先是Person p2 = p1;//复制对象的第一种方式:直接采用地址赋值
Java中的核心类_第1张图片
另外一种方式是Person p3 = (Person) p1.clone();//第二种方式:采用Object的clone()方法
Java中的核心类_第2张图片
另外需要注意的是clone()方法采用的是浅拷贝,如果需要深拷贝则需要将clone方法重写。
可以参考这篇文章:传送门

关于Object.finalize()方法

Java有垃圾回收器负责回收无用对象占据的内存资源。但也有特殊情况:假定你的对象(并非使用new)获得了一块“特殊”的内存区域,由于垃圾回收器只知道释放那些经由new分配的内存,所有它不知道如何释放该对象的这块“特殊”内存。为了应对这种情况,Java允许在类中定义一个名为finalize()的方法。它的工作原理“假定”是这样的:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。所以要是你打算用finalize(),就能在垃圾回收时刻做一些重要的清理工作。——节选自《Java编程思想》

public class Person implements Cloneable{
    private int id;
    private String name;

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public static void main(String[] args) throws Throwable {
        Person p1 = new Person(1001,"xiaoming");
        p1.finalize();//调用finalize方法
    }
}

关于Object.getClass()方法
关于Object.hashCode()方法
关于Object.toString()方法:返回包含类名和散列码的字符串,形如:类名@哈希代码值

public class Person implements Cloneable{
    private int id;
    private String name;

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public static void main(String[] args) throws Throwable {
        Person p1 = new Person(1001,"xiaoming");
        System.out.println(p1.getClass());
        System.out.println(p1.hashCode());
        System.out.println(p1.toString());
    }
}
class club.BOOKJava8.Person
1607521710
club.BOOKJava8.Person@5fd0d5ae

可以将Object.toString()进行重写

@Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

则此时输出的结果为:

Person{id=1001, name='xiaoming'}

下面介绍Java中的字符串类
有三种,其中不可变的是String,可变的是StringBuliderStringBuffer
首先介绍String
现在有String str1 = "abc";
Java中的核心类_第3张图片
此时若接着写:String str1 = "def";,千万记住,String创建的字符串是不可变的,刚才这么写其实际是在内存中创建一个新的字符串,字符串变量将引用新创建的字符串地址,而原来的字符串在内存中依然存在且内容不变,直至Java的垃圾回收系统对其进行销毁。
Java中的核心类_第4张图片
另外需要注意:String str2 = new String("lmn")创建的字符变量在堆中而不是常量池中,new出来的对象都是在堆中。
Java中的核心类_第5张图片

面试题:String str4= new String(abc")创建多少个对象?

  1. 在常量池中查找是否有"abc对象
  • 有则返回对应的引用实例
  • 没有则创建对应的实例对象
  1. 在堆中new—个 String(“abc”)对象
  2. 将对象地址赋值给str4创建一个引用所以,常量池中没有"abc"字面量则创建两个对象,否则创建一个对象,以及创建一个引用

变式String str3= new String("A"+"B");会创建多少个对象?

  • 常量池中:“A”“B”,“AB”:3个
  • 堆中:new String(“AB”):1个
  • 引用:str1:1个
  • 总共:5个

接下来介绍StringBuffer
String Buffer创建的字符串是可变的。可以通过append()insert()setCharAt()等方法进行操作。字符穿所引用的地址一直没有发生变化。要想获得StringBuffer的最终内容,可以调用toString()方法转化成一个String对象。

public class Test{
    public static void main(String args[]){
        StringBuffer sBuffer = new StringBuffer("abc");
        System.out.println(sBuffer);
        sBuffer.append("def");
        System.out.println(sBuffer);
        sBuffer.insert(1, 'i');
        System.out.println(sBuffer);
        sBuffer.setCharAt(1,'o');
        System.out.println(sBuffer);

    }
}
abc
abcdef
aibcdef
aobcdef

还有StringBuilder
StringBuffer是线程安全的,而 StringBuilder没有实现线程安全的,因此性能较好。如果只需要创建一个内容可变的字符串对象,不涉及线程安全、同步方面的问题,应优先考虑使用 Stringbuilder类。

public class Test{
    public static void main(String args[]){
        StringBuilder sBulider = new StringBuilder("abc");
        System.out.println(sBulider);
        sBulider.append("def");
        System.out.println(sBulider);
        sBulider.insert(1, 'i');
        System.out.println(sBulider);
        sBulider.setCharAt(1,'o');
        System.out.println(sBulider);
    }
}
abc
abcdef
aibcdef
aobcdef

你可能感兴趣的:(Java语言)