Java常用类

一、内部类

        在一个类的内部再定义完整的类。具有1)编译后可以产生独立的字节码文件。2)内部类可以直接访问外部类的私有成员而不破坏封装的特点。

1、成员内部类

        在类的内部定义,与实例变量和实例方法同级别。成员内部类是外部类的一个实例部分,创建内部类对象时,必须依赖外部类被对象,即要先创建外部类对象再创建内部类对象。当外部类和内部类存在重名属性时,会优先访问内部类属性,如要访问外部类的重名属性则使用Outer.this。成员内部类不能定义静态成员,但可以定义静态常量static final。

public class Outer {
    //实例变量
    private String name = "张三";
    private int age = 20;
    
    class Inner{
        private String address = "福建";
        private String phone = "110";
        //属性和外部类的属性名字相同 Outer.this
        private String name = "李四";
        
        public void show(){
            //打印外部类的属性
            System.out.println(Outer.this.name);
            System.out.println(Outer.this.age);
            //打印内部类的属性
            System.out.println(address);
            System.out.println(phone);
            System.out.println(name);//李四
    
        }
    }
public class TestOuter {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();
        inner.show();
        
    }
}

2、静态内部类

        不依赖外部对象,可以直接创建或通过类名访问,可以声明静态成员。例子中之所以先创建外部类再创建内部类是因为这是另一个Class文件,需要先创建外部类对象。

public class Outer {
    private String name = "张三";
    private int age = 18;
    
    static class Inner{
        private String address = "上海";
        private String phone = "111";
        //静态成员变量
        private static int count = 1000;
        
        public void show(){
            //调用外部类的属性
            Outer outer = new Outer();
            System.out.println(outer.age);
            System.out.println(outer.name);
            //调用静态内部类的属性和方法
            System.out.println(address);
            System.out.println(phone);
            //调用静态内部类的静态属性
            System.out.println(Inner.count);
        }
        public static void main(String[] args) {
            Inner inner = new Inner();
            System.out.println(new Inner().address);
        }
    }
public class TestOuter {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();
        inner.show();
        
    }
}

3、局部内部类

        定义在外部类的方法中,使用范围、作用范围和创建对象范围仅限于当前方法。局部内部类访问外部类当前方法中的局部变量时,因无法保证变量的声明周期与自身相同,变量必须修饰final。

public class Outer {
    private String name = "刘德华";
    private int age = 18;
    
    public void show(){
        final String address = "上海";
        class Inner{
            //局部内部类的属性
            private String phone = "111";
            private String email = "xxxxxxx.com";
            
            public void show2(){
                //访问外部类的属性
                System.out.println(name);//省略了Outer.this.name
                System.out.println(age);//如果方法show是静态的就不能直接访问,需要创建外部对象
                //访问内部类的属性
                System.out.println(this.phone);
                System.out.println(email);//省略了this
                //访问局部变量,jdk1.7要求:变量必须是常量final,jdk1.8后自动添加final
                System.out.println(address);
//这里已经不是调用address了而是System.out.println("上海");address消失了
            }
        }
        //方法并没有调用局部内部类,所以要创建局部内部类对象
        Inner inner = new Inner();
        inner.show2();
        
    }
public class TestOuter {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.show();
        
    }

4、匿名内部类

        没有类名的局部内部类(其实编译class文件可以看到有系统自动生成的名字的)一切特征都与局部内部类相同。匿名内部类必须继承一个父类或实现一个接口。其实匿名内部类就是定义类、实现类和创建对象的语法合并,要注意只能创建一个该类的对象!!!

public interface Usb {
    void seivice();
}
public static void main(String[] args) {
    Usb usb = new Usb(){
        @Override
        public void seivice() {
           System.out.println("连接电脑成功");
        }
    };
    usb.seivice();
}

二、Object类

        Object类是超类、基类、是所有类的直接或间接父类,位于继承树的最顶层。任何类如果没有书写extends显示继承某个类,都默认直接继承Object类,如果有则为间接类。Object类中所定义的方法是所有对象都具有的方法。可以用Object存储任何对象,作为参数可以接受任何对象,作为返回值则可以返回任何对象。

public class Student {
    
    private String name;
    private int age;
    
    public Student() {
    }
    
    public Student(String name, int age){
        super();
        this.name = name;
        this.age = age;
    }
    
    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;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

1)equals

        对于基本数据类型来说,没有equals方法;对于引用类型来说,equals比较的可能是内存地址,也可能是内存地址和值都比较,从equals的实现上来说,其实用的比较也是==,所以equals的具体比较得看重写后的方法。对于Object类型来说,equals方法比较的是两者的内存地址。但很多类型都重写了equals方法,例如常用的String类型比较的就是内存地址和值。==比较基本类型时比较的是值,比较引用类型时比较的是地址。

public class Equals {
    public static void main(String[] args) {
        Student s1 = new Student("aaa",20);
        Student s2 = new Student("bbb",22);
        System.out.println(s1.equals(s2));//没重写前是false 比的是地址
        Student s3 = new Student("小明",18);
        Student s4 = new Student("小明",18);
        System.out.println(s3.equals(s4));//重写后比较内容
    }
}

        equals也可以进行覆盖,覆盖步骤为1)比较两个引用是否指向同一个对象。2)比较obj是否为null。3)判断两个指向的实际对象类型是否一致。4)强制类型转换。5)依次比较各个属性值是否相同。

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Student student = (Student) o;
    return age == student.age &&
            Objects.equals(name, student.name);
}

2)getClass

        getClass()返回引用中存储的实际对象类型,通常用于判断两个引用中实际存储对象类型是否一致。

public static void main(String[] args) {
        Student s1 = new Student("aaa",20);
        Student s2 = new Student("bbb",22);
        //判断s1和s2是不是同一个类型
        Class class1 = s1.getClass();
        Class class2 = s2.getClass();
        if (class1 == class2){
            System.out.println("s1和s2属于同一个类型");
        }else {
            System.out.println("s1和s2不属于同一个类型");
        }
    }

3)finalize

        当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列。垃圾对象是指没有有效引用指向此对象的对象。垃圾回收指由GC销毁垃圾对象,释放数据存储空间。这里回收有两种机制,分别是自动回收机制:JVM的内存耗尽,一次性回收所有的垃圾对象;另一种是手动回收机制:使用System.gc();通知JVM进行垃圾回收。

4)hashCode

        用来返回该对象的哈希码值。哈希值根据对象的地址或字符串或数字使用hash算法计算出来的int类型的数值。一般情况下相同对象返回相同的哈希码。这里s1和s2哈希码不同不是因为内容不同,是因为两个不为同一个对象。

Student s1 = new Student("aaa", 22);
Student s2 = new Student("bbb", 21); 
System.out.println(s1.hashCode());//2986934
System.out.println(s2.hashCode());//3017716
Student s3 = s1;//把s1的地址给s3
System.out.println(s3.hashCode());//2986934

5)toString

        返回该对象的字符串表示。返回的对象为类时,返回的是位置@16进制哈希值。toString()可以根据不同需求覆盖方法,如下展示对象的各个属性值。

public static void main(String[] args) {
        Student s1 = new Student("aaa",20);
        Student s2 = new Student("bbb",22);
    
        System.out.println(s1.toString());//com.lhp.Class.Object.Student@79032d84
        System.out.println(s2.toString());//位置@哈希值(16进制)
    }

三、包装类

        基本数据类型所对应的引用数据类型,默认值是null。装箱是基本类型转换引用类型,eg:在栈中定义了一个10,放入堆中引用。拆箱是引用类型转换成基本类型。jdk1.5后提供自动装箱和拆箱,class文件反编译后还是装箱和拆箱。

int num1 = 10;
//使用Integer类创建对象
//装箱
Integer integer1 = new Integer(num1);
Integer integer2 = Integer.valueOf(num1);
System.out.println(integer1);
System.out.println(integer2);
//拆箱,引用类型转换成基本类型
Integer integer3 = new Integer(100);
int num2 = integer3.intValue();
System.out.println(num2);

int age = 30;
//自动装箱
Integer integer4 = age;
System.out.println(integer4);
//自动拆箱
int age2 = integer4;
System.out.println(age2);

        数字使用Integer类创建对象,基本类型转换成字符串有两种方法,一是直接加空字符串,二是使用Integer的toString方法;字符串转换成基本类型使用parsexxx();Boolean字符串形式转换成基本类型true转换成true,其他的都是false。

//基本类型转成字符串
int n1 = 15;
String s1 = n1 + "";//+空字符串
String s2 = Integer.toString(n1);//Integer中的toString方法
String s3 = Integer.toString(n1,16);//16进制
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
        
//字符串转成基本类型
String str = "150";
int n2 = Integer.parseInt(str);
System.out.println(n2);
String str2 = "true";
boolean b1 = Boolean.parseBoolean(str2);
System.out.println(b1);

        Java预先创建了256个常用的整数包装类型对象称为整数缓冲区,可以直接进行复用。即从堆中的整数缓冲区里把已经存在的数字的地址放入栈中,范围是-127~127,自动装箱时使用Integer.valueOf(),如果不在整数缓冲区内的话使用new Integer()。

Integer integer5= new Integer(100);
Integer integer6= new Integer(100);
System.out.println(integer5 == integer6);//false引用对象 比较的是地址
Integer integer7 = 100;
Integer integer8 = 100;
System.out.println(integer7 == integer8);//true
Integer integer9 = 200;
Integer integer10 = 200;
System.out.println(integer9 == integer10);//false

四、String类

        1)字符串是常量,创建后不可改变,字符串字面值存储在字符串池中,可以共享,字符串串池在方法区中,JDK不同版本字符串池不一定字方法区里,7.0后被移到了堆中。如果是直接赋值的话是产生一个对象,字符串池中储存;如果是new一个赋值的对象的话是产生两个对象,在堆和池中各一个,比较浪费空间。重新给原来有值的字符串变量赋值时,不是直接修改数据,而是重新在方法区中开辟了一个空间放入字面值,原来的常量就成了垃圾。

String name = "hello";//”hello“常量存储在字符串池中,
name = "zhangsan";//"zhangsan"赋值给name变量,原来的hello成为了垃圾
String name2 = "zhangsan";
String str = new String("java");
String str2 = new String("java");
System.out.println(str == str2);//false
System.out.println(str.equals(str2));//true

String content = "java 是最好的java编程语言,java";

length();返回字符串长度。

System.out.println(content.length());//22

charAt(int index);根据下标获取字符串。

System.out.println(content.charAt(0));//j
System.out.println(content.charAt(content.length()-1));//a

contains(String str);判断当前字符串中是否含有str。

System.out.println(content.contains("java"));
System.out.println(content.contains("python"));

toCharArray();将字符串转换成数组。

System.out.println(Arrays.toString(content.toCharArray()));
//[j, a, v, a,  , 是, 最, 好, 的, j, a, v, a, 编, 程, 语, 言, ,, j, a, v, a]

indexOf(String str);查找str首次出现的下标,存在则返回下标,不存在则返回-1。

System.out.println(content.indexOf("java"));//0
System.out.println(content.indexOf("java",4));//9 从4下标开始找

lastIndexOf(String str);查找字符串在当前字符串中最后一次出现的下标索引。

System.out.println(content.lastIndexOf("java"));//18

trim();去掉字符串前后的空格。

String content2 = "    Hello world ";
System.out.println(content2.trim());

toUpperCase();将小写转换成大写。

System.out.println(content2.toUpperCase());
System.out.println(content2.toLowerCase());

endWith(String str);判断字符串是否以str结尾。

String filename = "hello.java";
System.out.println(filename.endsWith("java"));
System.out.println(filename.startsWith("hello"));

replace(Char oldChar,Char newChar);把旧字符替换成新字符。

 System.out.println(content.replace("java", "python"));

split(String str);根据str进行拆分。

String say = "java is the best   programing language,xiang";
String[] arr = say.split("[ ,]+");//用空格和逗号,且多个逗号和空格算一个
System.out.println(Arrays.toString(arr));
System.out.println(arr.length);//7
for (String string : arr){
    System.out.print(string+" ");
}//java is the best programing language xiang false

compareTo();根据字典表里的顺序比较大小。从第一个字符开始比,如果相同则下一个字符比较,不同则相减。如果被比较值的长度比比较值短,且没比出结果则比较长度。

String s1 = "hello";
String s2 = "HELLO";
System.out.println(s1.equals(s2));//false
System.out.println(s1.equalsIgnoreCase(s2));//忽略大小写比较true
String s3 = "abc";//97
String s4 = "xyz";//123
System.out.println(s3.compareTo(s4));//-26
String s5 = "abc";
String s6 = "abcxzy";
System.out.println(s5.compareTo(s6));//-3 这里因为abc后面没有东西比了 所以比长度

2)可变长字符串

        可变长字符串有两种使用方法,分别是StringBuffer和StringBuilder。StringBuffer:可变长字符串,由JDK1.0提供,运行效率比StingBuilder慢,线程安全。StringBuilder:可变长字符串,JDK5.0提供,线程不安全,常用于单线程。可变长字符串比String效率高,更省内存。

long start = System.currentTimeMillis();
String string="";
for (int i = 0;i < 99999;i++){
    string+=i;
}
System.out.println(string);
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - start));//8992
        
long start2 = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0;i < 99999;i++){
    sb.append(i);
}
System.out.println(sb.toString());
long end2 = System.currentTimeMillis();
System.out.println("用时:" + (end2 - start2));//9

常用append();insert();replace();delete();来进行追加、添加、替换和删除。

StringBuilder sb = new StringBuilder();
sb.append("java number one");
System.out.println(sb.toString());
sb.append(" java good");
System.out.println(sb.toString());
sb.insert(0,"我在最前面");
System.out.println(sb.toString());
sb.replace(0,5,"Hello,");
System.out.println(sb.toString());
sb.delete(0,5);
System.out.println(sb.toString());
//清空
sb.delete(0,sb.length());
System.out.println(sb.toString());

五、BigDecimal

        因为浮点数的采用近似计算,在一些需要精确计算的时候就会产生精度缺失,所以一般使用BigDecimal来精确计算浮点数。BigDecimal使用add(new BigDecimal);subtract(new BigDecimal);multiply(new BigDecimal);divide(new BigDecimal);来进行加减乘除。注意除法如果除不尽的话会报错,可以采用四舍五入来避免报错。

BigDecimal bd1 = new BigDecimal("1.0");//一定要为字符串,不然还是可能精度缺失
BigDecimal bd2 = new BigDecimal("0.9");
BigDecimal r1 = bd1.subtract(bd2);//减法
System.out.println(r1);
BigDecimal r2 = bd1.add(bd2);//加法
System.out.println(r2);
BigDecimal r3 = bd1.multiply(bd2);//乘法
System.out.println(r3);
BigDecimal r4 = new BigDecimal("1.4").subtract(new BigDecimal(0.5)).divide(new BigDecimal("0.9"));
//(1.4 - 0.5)/0.9
System.out.println(r4);
BigDecimal r5 = new BigDecimal("10").divide(new BigDecimal("3"),2,BigDecimal.ROUND_HALF_UP );
//10/3 这里保留两位小数,四舍五入
System.out.println(r5);

六、Date

        Date表示特定的瞬间,精确到毫秒。Date类中的大部分方法都已经被Calender类中的方法所取代。 

        1秒 = 1000毫秒         1毫秒 = 1000微秒         1微秒 = 1000纳秒

//今天
Date date1 = new Date();
System.out.println(date1.toString());//Fri Feb 11 15:03:36 CST 2022
System.out.println(date1.toLocaleString());//2022-2-11 15:03:36
//昨天
Date date2 = new Date(date1.getTime() - 60*60*24*1000);//精确到毫秒
System.out.println(date2.toLocaleString());//2022-2-10 15:03:36
boolean b1 = date1.after(date2);//今天在昨天的后面
System.out.println(b1);//true
boolean b2 = date1.before(date2);//今天在昨天的前面
System.out.println(b2);//false
//compareTo();比较的是毫秒值 返回1,0,-1 代表正负数和0
int d = date1.compareTo(date2);
System.out.println(d);
date1.equals(date2);//flase

七、Calender

        Calender常用于日历,是对Date的改善。注意创建Calender对象时一般用Calendar calendar = Calendar.getInstance();静态方法返回子类对象,而不是new。Calender使用getTime();来返回时间。用get();来获取需要的时间信息,要注意因为国外的月份的记录方法习惯不同,所以获取月份时是从0~11。修改时间一般用set和add来修改时间。可以用getActualMaximum();来获取最大值。

//创建Calendar对象
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getTime().toLocaleString());
System.out.println(calendar.getTimeInMillis());
//获取时间信息
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);//Date
int hour = calendar.get(Calendar.HOUR_OF_DAY);//HOUR12小时,HOUR_OF_DAY24小时
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
System.out.println(year+"年"+(month+1)+"月"+day+"日"+hour+":"+minute+":"+second);
//修改时间
Calendar calendar2 = Calendar.getInstance();
calendar2.set(Calendar.DAY_OF_MONTH,5);
System.out.println(calendar2.getTime().toLocaleString());
calendar2.add(Calendar.HOUR,-1);//减一小时
System.out.println(calendar2.getTime().toLocaleString());
int max = calendar2.getActualMaximum(Calendar.DAY_OF_MONTH);
int min = calendar2.getActualMinimum(Calendar.DAY_OF_MONTH);
System.out.println(max);
System.out.println(min);

八、SimpleDateFormat

        SimpleDateFormat一般用来格式化时间(日期 —> 文本)或解析(文本 —> 日期)。格式化用format();解析用parse();格式化时年用y,月用M,日用d,小时用H(0~23)h(1~12),分钟用m,秒用s,毫秒用S。

SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date date = new Date();
//格式化date
String str = sdf.format(date);
System.out.println(str);
//解析
Date date2 = sdf.parse("1999年11月22日 14:15:55");
System.out.println(date2);

九、System

        System构造方法是私有的,不要要创建对象使用。常用的有arraycopy();数组的复制,这里src表示源数组,srcPos表示从哪个位置开始复制,dest表示目标数组,length表示复制的长度。currenTimeMillis();获取毫秒数。gc();告诉垃圾回收期回收。exit(int  status);退出JVM,推出后的语句均不执行。

int[] arr = {20,19,29,4,55,90,1,2};
int[] dest = new int[8];
System.arraycopy(arr,4,dest,4,4);
for (int i = 0; i < dest.length; i++) {
    System.out.println(dest[i]);
}
//Array.copyOf(original,newLength)其实也是用System.arraycopy实现
System.out.println(System.currentTimeMillis());
long start = System.currentTimeMillis();
for (int i = 0;i < 99999;i++){
    int result =+i;
}
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - start));
System.gc();
System.exit(0);
System.out.println("hello");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值