面向对象基础篇 – 常用类解析

面向对象基础篇 – 常用类解析

Object类

Object类是所有类的最终父类,也就是说,我们定义一个类,哪怕不写extends Object ,此时这个类也是默认继承Object的,

并且可是使用继承来的方法

class Demo{
    
}
class Test{
    public static void main(string[] args){
        Demo demo = new Demo();
        System.out.println(demo.hashCode());
        //可以看到,尽管我们在Demo类中并没有定义hashCode方法,但我们依旧可以使用
        //这是因为,我们继承了Object类,而Object类中是存在这个方法的
    }
}
Object类常用方法解析
  • native void registerNatives()
 private static native void registerNatives();
    static {
        registerNatives();
        //本地方法 主要用于在内存中注册对象信息 用于创建对象使用的
    }
  • getClass
    @HotSpotIntrinsicCandidate
    public final native Class<?> getClass();
    //本地方法 获取JVM运行时的字节码文件对象 反射知识中会学到
class Test{
    public static void main(string[] args){
        Object demo = new Object();
        System.out.println(demo.getClass());
        //输出 class java.lang.Object
        //该方法不能被重写
    }
}
  • hashCode()
    @HotSpotIntrinsicCandidate
    public native int hashCode();
//本地方法 获取对象的哈希值-作为元素在哈希表中存储位置 默认内容 就是对象在堆内存中的地址
/*
子类可以重写 在哈希表中 子类的哈希值应该由子类的内容来决定
        为什么?因为如果不去按照子类的内容来定义哈希值 哈希值默认就是对象的地址
        任何一个对象的地址都是不一样的,在哈希表中就不会产生哈希冲突,退化成了纯粹的一维数组
  */
//例如,学生类,用学号代表哈希码
class Student{
    long studyNum = 20408030314 ;
     @Override
     public int hashCode() { //根据类自身的内容来计算哈希值
        return studyNum;
    }
}
  • equals()
public boolean equals(Object obj) {
        return (this == obj);
}
/*
对比当前 对象this 与 传入对象obj 的相等性
        Object中 默认比两个对象的地址 == 其实比的就是两个变量空间中的内容
            基本数据类型 == 比的就是常量值
            引用数据类型 == 比的就是地址值
        子类重写时,应该按照子类的内容来进行比较!        
  */
//不重写
class Demo{
    int num ;
    public Demo(int num){
        this.num = num ;
    }
}
class Test{
    public static void main(String[] args){
        Demo demo1 = new Demo(10);
        Demo demo2 = new Demo(10);
        System.out.println(demo1.equals(demo2))//输出false
            //在没有重写equals方法的情况下,比较的是两个对象的存储地址
            //虽然demo1和demo2的num值都是10,但他们是两个独立的对象,存储地址是不同的,因此返回false
    }
}
//重写
//不重写
class Demo{
    int num ;
    public Demo(int num){
        this.num = num ;
    }
    public boolean equals(Object obj) {
        return (this.num == obj.num);
    }
    
}
class Test{
    public static void main(String[] args){
        Demo demo1 = new Demo(10);
        Demo demo2 = new Demo(10);
        System.out.println(demo1.equals(demo2))//输出true
            //此时,我们重写了equals方法,让他比较的是每个对象的num属性。而num又是基本数据类型,并且值相等,因此返回true
    }
}
  • toString()
public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    //默认返回类名+@+地址值的十六进制形式
}
//重写
class Demo{
    String name ;
    int age ;
    public Demo(String name,int age){
        this.name = name ;
        this.age = age ;
    }
    public String toString(){
        return "Demo" + "{name : " + name + "age :"+age+"}";           
    }
}

class Test{
    public static void main(String[] args){
        Demo demo = new Demo("小明"10);
        System.out.println(demo);//此时输出对象,默认调用他的toString方法 ,
        //输出 Demo { name : 小明 age : 10 }
    }
}
  • clone()
protected native Object clone() throws CloneNotSupportedException;
    //做一个该对象的副本/拷贝
 @Override
    protected Object clone() throws CloneNotSupportedException {
       return super.clone();   //浅克隆 仅仅把这个对象的属性重新进行复制而已

        //基本数据类型直接复制即可 name age互不相扰
        //引用数据类型直接复制是不行的 
        //需要把引用数据类型再次进行克隆 ——深克隆
        //如果克隆层次较深 上述方法就显得太复杂了!
    }
class Car implements Cloneable{
    String band;

    public Car(String band) {
        this.band = band;
    }

    @Override
    public String toString() {
        return band;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        rsheneturn super.clone();
    }
    
}
//一个类实例的对象如果要被克隆,则这个类要实现Cloneable接口
//该接口中并未任方法。只是作为一个可以被克隆的标记
class Demo implements Cloneable{
    String name ;
    int age  ;
    Car car ;
     @Override
    protected Object clone() throws CloneNotSupportedException {
        //return super.clone();   //浅克隆 仅仅把这个对象的属性重新进行复制而已
        Object obj = super.clone();
        Demo newDemo = (Demo) obj;
        other.car = (Car) car.clone(); //深克隆,对引用属性再次克隆
        return other;
    }
}

基本数据类型包装类

有缓存,-128 ~127

  • byte – Byte
  • short – Short
  • int – Integer
  • long – Long

小数点没有缓存

  • float – Float
  • double --Double

有缓存, 0 ~ 128

  • char --Character

无缓存

  • boolean – Boolean
class Demo{
    public static void main(String[] args){
        int i1 = 10;
        Integer i2 = 10 ;
        Integer i3 = new Integer(10);
        System.out.println(System.identityHashCode(i1)); 
        System.out.println(System.identityHashCode(i2));
        //发现 i1 和 i2 的 哈希值是一样的
        System.out.println(System.identityHashCode(i3));
        //i3 的哈希值 和他们是不一样的
        System.out.println(i1 == i2); //true
        System.out.println(i2 == i3); //false
        System.out.println(i3 == i1); //true
        /*
        这是因为, 在基本数据类型和基本数据包装类比较时,其实包装类会默认拆分
        i1 == i2 等价于  i1 == i2.intValue();
        intValue()方法返回的是对象的value,也就是10 ,因此 true
        而包装类型和包装类型比较时,默认比较的是 对象的地址
        因此 i2 == i3 输出 false
       */
        System.out.println(i1 + i2);//20
        System.out.println(i2 + i3);//20
        /*
        可见,包装类型 或 基本类型 在与 包装类型 进行运算时,也会自动拆分
        i1 + i2 等价于 i1 + i2.intValue();
        i2 + i3 等价于 i2.intValue()+i3.intValue();
    }
}
class Demo{
    public static void main(String[] args){
        Integer i1 = 10 ;
        Integer i2 = Integer.valueOf(10);
        /*直接让Integer 对象 = 一个数值
        就相当于 调用了Integer.valueOf(int i);方法
        输出 两个的哈希值,我们发现是一样的
        */
    }
    // valueOf方法
        @HotSpotIntrinsicCandidate
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    //其中 ,IntegerCache.low = -128 ;IntegerCache.high = 127
    /*
    也就是说,如果,给定值在这个范围之间,是不会创建对象的,而是直接在,缓存中提取复用
    */
}

常用方法
  • parseInt() 字符串 转整数,默认10进制
class Demo{
    public static void main(String[] args){
        String s = "123";
        int i = Integer.parseInt(s);//10进制123
        System.out.println(Integer.parseInt("10",2));//2进制的10 ,1010
    }
}
  • toBinaryString(int i) 转二进制字符串
  • toHexString(int i) 转16进制
  • toOctalString(int i) 转8进制
class Demo {
    public static void main(String[] args){
        int i = 10 ;
        System.out,println(Integer.toBinaryString(i));//1010
        System.out,println(Integer.toHexString(i));//a
        System.out,println(Integer.toOctalString(i));//12
    }
}
  • reveser(int i) ;字节反转
class Demo{
    public static void main(String[] args){
        System.out.println(Integet.reveser(123456));//38240256
    }
}
  • Character.is…();判断是否是什么
public class Demo {
    public static void main(String[] args) {
        System.out.println(Character.isDigit('8')); //是不是数字 true
        
        System.out.println(Character.isLetter('5'));//是不是字母 false
        //等等...
    }
}

String 和 StringBuilder 和 StringBuffer

String

public final class String 证明String不能被继承

implements java.io.Serializable, Comparable, CharSequence
Serializable表示字符串可以被序列化存储到硬盘
Comparable 表示字符串自身具有可比较的功能
CharSequence 表示字符串是一个字符序列

  • private final char value[];

​ 字符串本身就是一个字符数组(JDK8之后是字节数组) 数组本身长度一旦确定,则不可改变
​ 数组中的元素可以改变的
​ final 数组的对象不能改变 但是内部的元素依旧可以改变
​ private 禁止外界访问
​ 目前来看String中的value外界不可访问,在内部value是对象不可变的,但是并没有强制要求内容不可变
​ 只不过是对字符数组的操作 尤其是在修改之类的操作时 都是另创建数组或字符串操作的 并没有在原数组上进行

关于字符常量池String Table

该常量池会存储代码中直接出现的那些字符序列

class Dmeo{
      public static void main(String[] args) {
          String s1 = "Hello";
          String s2 = "World";
          String s3 = "Hello" + "World";
          String s4 = "HelloWorld";
          //以上直接出现的字符串,会存储在字符常量池中,如果后续出现,则会继续复用
          String s5 = new String("HelloWorld");
          System.out.println(s4 == s5);//false
          //而对于new 的字符串对象,他里面的value数组存储的就是 常量池中已存在的地址
          String s6 = s1 + s2; 
          String s7 = s1 + "World"; 
          System.out.println(s4 == s7);//false
          //使用intern函数,可以获取它在常量池中的地址
          System.out.println(s4 == s7.intern());//true
          //intern的含义就是将字符串对象中的value装载都常量池中 并返回其地址
          //如果池中已经存在,则直接复用,否则新建
         
      }
}
常用方法
  • charAt(int index) 返回指定索引的字符
public class Demo {
    public static void main(String[] args) {
        String str = "123456";
        System.out.println(str.charAt(2));//输出3
    }
}
  • length()返回字符串的长度
public class Demo {
    public static void main(String[] args) {
        String str = "123456";
        System.out.println(str.length()); //6
    }
}
  • compareTo(),按字典序比较两个字符串
public class Demo {
    public static void main(String[] args) {
        String str = "123456";
        String str2 = "234567";
        System.out.println(str.compareTo(str2)); //-1 (1-2)
    }
}
  • equals();比较两个字符串的具体内容
public class Demo {
    public static void main(String[] args) {
        String str = "123456";
        String str2 = "234567";
        System.out.println(str.equals(str2));
    }
}
  • indexOf();返回指定字符在字符串中第一次上出现索引
public class Demo {
    public static void main(String[] args) {
        String str = "123456";
        String str2 = "23";
        System.out.println(str.indexOf(str2)); //1
    }
}
  • startsWith();是否以指定字符或字符串开头
  • endsWith();是否以指定字符或字符串结尾
public class Demo {
    public static void main(String[] args) {
        String str = "23456";
        String str2 = "23";
        System.out.println(str.startsWith(str2)); //true
        System.out.println(str.endsWith("6")); //true
    }
}
  • subString (),返回一个子序列

  • matches();是否符合正则表达式

  • replace();替换字符

  • toUpperCase();转大写

  • toLowerCase();转小写

  • tirm();返回去掉首尾空白符的字符串

StringBuilder

一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。
该类被设计用作 StringBuffer 的一个简易替换,
用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。
如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。

extends AbstractStringBuilder implements Appendable, CharSequence
经过对AbstractStringBuilder的观赏 发现 对字符串的操作都是在value数组上进行的

  • 特点
    • 可变的字符序列,本质上是一个可修改可变长的字符数组而已
    • 字符缓冲区
    • 线程不安全
    • 单线程模式下速度较快
public class Demo {
    public static void main(String[] args) {
        //拼接字符串
        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        String s = "";
        s +='[';
        for (int i = 0; i < arr.length; i++) {
            s += arr[i];
            if (i == arr.length - 1) {
                s += ']';
            } else {
                s += ',';
                s += ' ';
            }
            System.out.println(s);
        }
    }
}

/*
输出
[1, 
[1, 2, 
[1, 2, 3, 
[1, 2, 3, 4, 
[1, 2, 3, 4, 5, 
[1, 2, 3, 4, 5, 6, 
[1, 2, 3, 4, 5, 6, 7, 
[1, 2, 3, 4, 5, 6, 7, 8, 
[1, 2, 3, 4, 5, 6, 7, 8, 9]
*/
/*
上面说到,s += "";的过程是创建对象的,所以,普通的字符串拼接会造成创建大量的中间对象,字符串常量,造成空间浪费
而StringBuilser 则有效解决了这个问题
*/

class Demo{
     public static void main(String[] args) {
        //拼接-> [1,2,3,4,5,6,7,8,9]
        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        StringBuffer s = new StringBuffer();
        s.append('[');
        for (int i = 0; i < arr.length; i++) {
            s.append(arr[i]);
            if (i == arr.length - 1) {
                s.append(']');
            } else {
                s.append(',');
                s.append(' ');
            }
        }
        System.out.println(s.toString());
     }
}
/*
输出
[1, 2, 3, 4, 5, 6, 7, 8, 9]
*/
常用方法
  • append();追加
public class Demo {
    public static void main(String[] args) {
        StringBuilder str = new StringBuilder("");
        str.append(5);
        str.append("我");
        System.out.println(str);
    }
}
// 输出  5我
  • setCharAt();修改指定位置的字符
public class Demo {
    public static void main(String[] args) {
        StringBuilder str = new StringBuilder("dsdaf");
        str.setCharAt(0,'k');
        System.out.println(str);
    }
}
//输出 ksdaf
  • delete();删除指定位置的字符串
public class Demo {
    public static void main(String[] args) {
        StringBuilder str = new StringBuilder("dsdaf");
        str.delete(0,2);
        System.out.println(str);
    }
}
//输出 daf
  • insert();在指定位置插入字符序列
public class Demo {
    public static void main(String[] args) {
        StringBuilder str = new StringBuilder("dsdaf");
        str.insert(0,'5');
        System.out.println(str);
    }
}
//输出 5dsdaf
  • reverse();字符串翻转
public class Demo {
    public static void main(String[] args) {
        StringBuilder str = new StringBuilder("dsdaf");
        System.out.println(str.reverse());
    }
}
//输出 fadsd
  • trimToSize() 剔除未使用空间
StringBuffer

StringBuffer 是线程安全的 适用于多线程的情况下

和StringBuilder来比较的话 StringBuffer中大部分方法都有synchronized修饰

synchronized同步的De

BigInteger 和 BigDecimal

在Java中 long与double,是最长的基本数据类型

而对于超出long与double所能承受的最大范围时,我们可以使用 BigInteger 和 BigDecimal

无论是BigInteger还是BigDecimal,它们的本质其实就是数组

后续的四则运算其是都是基于数组进行的四则运算

常用方法
  • add();加
  • subtract();减
  • multiply();乘
  • divide();除
  • remainder();取余
public class Demo {
    public static void main(String[] args) {
        BigInteger i1 = new BigInteger("123");
        BigInteger i2 = new BigInteger("456");
        System.out.println(i1.add(i2));
        System.out.println(i1.subtract(i2));
        System.out.println(i1.multiply(i2));
        System.out.println(i1.divide(i2));
        System.out.println(i1.remainder(i2));

    }
}
/*
输出
579
-333
56088
0
123
*/
  • 转基本类型
public class Demo {
    public static void main(String[] args) {
        BigInteger i1 = new BigInteger("123");
        BigInteger i2 = new BigInteger("456");
        long num = i1.longValue();//精确转换
        long num2 = i2.longValueExact();//不精确转换,超出范围会抛出异常
    }
}

  • BigDecimal

其实就是 BigInteger + scale

scale 小数位个数

时间类

时间戳

从1970年1月1日00:00开始至今所有的毫秒值

System.currentTimeMillis();//获取时间戳

java.util.Date 日期类
java.sql.Date 子类 年月日
java.sql.Time 子类 时分秒
java.sql.Timestamp 子类 年月日时分秒
java.util.Calendar 日历类
java.text.DataFormat 日期格式化类
java.text.SimpleDateFormat 子类

日期
public class Demo {
    public static void main(String[] args) {
        java.util.Date date1 = new java.util.Date();
        //根据当前时间戳创建对象
        java.sql.Date date2 = new java.sql.Date(date1.getTime());
        java.sql.Time date3 = new java.sql.Time(date1.getTime());
        java.sql.Timestamp date4 = new java.sql.Timestamp(date1.getTime());

        System.out.println("java.util.Date : "+date1);
        System.out.println("java.sql.Date : "+date2);
        System.out.println("java.sql.Time : "+date3);
        System.out.println("java.sql.Timestamp : "+date4);

    }
}
/*
输出
java.util.Date : Thu Oct 13 19:38:33 CST 2022
java.sql.Date : 2022-10-13
java.sql.Time : 19:38:33
java.sql.Timestamp : 2022-10-13 19:38:33.193
*/

        //CST可视为中国、美国、澳大利亚、古巴的时区
        //GMT 格林尼治标准时间
        //UTC 统一的标准时间
java.util.Date
public class Demo {
    public static void main(String[] args) {
        java.util.Date date = new java.util.Date();//默认当前时间戳创建对象
        java.util.Date date1 = new java.util.Date(10000L);//指定时间戳创建对象
        System.out.println(date);
        //Thu Oct 13 20:13:17 CST 2022
        System.out.println(date1);
        //Thu Jan 01 08:00:10 CST 1970
        System.out.println(date.getTimezoneOffset());//
        //-480
        //返回与格林尼治时间的时差,以分钟计时的,正好8个小时
        //输出-480 意味着北京时间-480分钟等于GMT时间
        System.out.println(date.getTime());
        //1665664427912
        //返回时间戳
        System.out.println(date.after(date1));
        //true
        System.out.println(date.before(date1));
        //false
        //比较的是毫秒值
    }
}
  • toString
 public String toString() {
        // "EEE MMM dd HH:mm:ss zzz yyyy";
        BaseCalendar.Date date = normalize();
        StringBuilder sb = new StringBuilder(28);
        int index = date.getDayOfWeek();
        if (index == BaseCalendar.SUNDAY) {
            index = 8;
        }
        convertToAbbr(sb, wtb[index]).append(' ');                        // EEE
        convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' ');  // MMM
        CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd

        CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');   // HH
        CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
        CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
        TimeZone zi = date.getZone();
        if (zi != null) {
            sb.append(zi.getDisplayName(date.isDaylightTime(), TimeZone.SHORT, Locale.US)); // zzz
        } else {
            sb.append("GMT");
        }
        sb.append(' ').append(date.getYear());  // yyyy
        return sb.toString();
    }

/*
可以看到 默认输出
  "EEE MMM dd HH:mm:ss zzz yyyy";
   周  月   日 时  分 秒  时区 年
   如何按照自己的行为习惯输出,看下面的DateFormat类
   */

日历
public class Demo {
    public static void main(String[] args) {
        java.util.Calendar calendar = java.util.Calendar.getInstance();

        System.out.println(" java.util.Calendar :" +calendar.getTime());

    }
}

/*
输出
 java.util.Calendar :Thu Oct 13 19:46:09 CST 2022
 */

java.text.DataFormat 日期格式化类

自定义时间格式

可以将 text 转化为 date

也可以将 date 转化为 text

//date -》text
public class Demo {
    public static void main(String[] args) {
        java.util.Date date = new java.util.Date();
        java.text.SimpleDateFormat simpleDateFormat = new java.text.SimpleDateFormat();
        String str = simpleDateFormat.format(date);
        System.out.println(str);
        //2022/10/13 下午8:56  默认输出 年/月/日 时辰时间
    }
}
//text -> date
public class Demo {
    public static void main(String[] args) throws ParseException {
        java.text.SimpleDateFormat simpleDateFormat = new java.text.SimpleDateFormat();
        String str2 = "2011/10/1 上午5:31";
        java.util.Date date1 = simpleDateFormat.parse(str2);
        System.out.println(date1);
        //Sat Oct 01 05:31:00 CST 2011
    }
}

//自定义格式
//date -> text
public class Demo {
    public static void main(String[] args) throws ParseException {
        java.text.SimpleDateFormat simpleDateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm");
        java.util.Date date1 = new java.util.Date();
        String str = simpleDateFormat.format(date1);
        System.out.println(str);
        //2022-10-13 21:10
    }
}
//自定义格式
//text->date
public class Demo {
    public static void main(String[] args) throws ParseException {
        java.text.SimpleDateFormat simpleDateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        java.util.Date date = simpleDateFormat.parse("2022-10-07 16:21:59") ;
        System.out.println(date);
        //Fri Oct 07 16:21:59 CST 2022
    }
}

字母含义

y   年   yyyy 2022 yy 22
M   月   MM 07
w   周   ww 27
W   月份中的周数
D   年中的第几天
d   月中的第几天
F   月份中星期
E   星期中的天数
H   小时0-23
k   小时数1-24
K   小时数0-11
h   小时数1-12
m   分钟数
s   秒数
S   毫秒数
z   时区
Z   时区
常见的时间格式
//常见的时间格式
public class DateTest04 {
    public static void main(String[] args) throws ParseException {
        {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = dateFormat.parse("2015-08-08 15:30:31");
            System.out.println(date);
        }
        {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-M-d");
            Date date = dateFormat.parse("2015-12-12");
            System.out.println(date);
        }
        {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-M-d H:m:s");
            Date date = dateFormat.parse("2015-12-12 18:8:30");
            System.out.println(date);
        }
        {
            SimpleDateFormat dateFormat = new SimpleDateFormat("MMM d, yyyy h:m:s aa", Locale.ENGLISH);
            Date date = dateFormat.parse("Aug 28, 2015 6:8:30 PM");
            System.out.println(date);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值