常用工具类


内部类分类

  • 成员内部类
  • 静态内部类
  • 局部内部类
  • 匿名内部类

内部类的概念

什么是内部类?

在一个类的内部再定义一个完整的类

特点:

  • 编译之后会生成独立的字节码文件

  • 内部类可直接访问外部类的私有成员,而不破坏封装

  • 可为外部类提供必要的内部功能组件

内部类是否会再次生成class文件?

答案是的

例如我自己写了一个匿名内部类

class生成目录下找到了

成员内部类

//成员内部类
public class Outer {
    //实例变量
    private String name = "张三";
    private  int age = 23;

    //内部类
    class Inner{
        private String address = "hangzhou";
        private String phone = "120";

        //方法
        public void show(){
            //外部类
            System.out.println(name);
            System.out.println(age);
            //内部类
            System.out.println(address);
            System.out.println(phone);
        }
    }
}

外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象。

public class Test {
    public static void main(String[] args) {
        //创建外部类对象
        Outer outer = new Outer();
        //创建内部类对象
        Outer.Inner inner = outer.new Inner(); 
        //嫌麻烦可以换成这样
        Outer.Inner inner = new Outer().new Inner();
        inner.show();
    }
}

当外部类、内部类存在重名属性时,会优先访问内部类属性。

//成员内部类
public class Outer {

    //实例变量
    private String name = "张三";

    //内部类
    class Inner{
        private String name ="李四";

        //方法
        public void show(){
            System.out.println(name);
            //如果需要访问内部类对象,改成这样
            System.out.println(Outer.this.name);

        }
    }
}

成员内部类不能定义静态成员的。但是可以定义静态常量

private static final String country = "中国";

静态内部类

//静态内部类
public class Staticc {
    //私有属性
    private String name = "XXX";
    private int age = 12;
    //静态内部类
    static class Inner{
        //静态内部类中的私有属性
        private String address = "hangzhou";
        private String phone = "120";
        //静态内部类中静态的私有属性
        private static final String country = "中国";
        public void show(){
            Staticc staticc = new Staticc();
            System.out.println(staticc.age);
            System.out.println(Inner.country);
        }
    }
}

只能直接访问外部类的静态成员(实例成员需要实例化外部类的对象)

public class TestSt {
    public static void main(String[] args) {
        Staticc.Inner inner = new Staticc.Inner();
        inner.show();
    }
}

局部内部类

定义在外部类的方法中,作用范围和创建对象范围仅限于当前方法。

public class part {
    //实例变量
    private String name = "张三";
    private  int age = 23;
    public void show(){
        //定义局部变量
        final String address="sz";
        //局部类-局部内部类前面不能加任何访问修饰符public
        //局部变量 本身就是 一个访问权限 的设定啊。 只能在局部调用
        //定义在方法中的变量叫局部变量,局部变量的有效范围就是方法内,在局部变量中加上public,或者其他修饰符的话(编译都通不过),就破坏了局部变量的范围,可以说局部变量是为方法而生的。局部变量中的局部就已经说明了范围
        class Inner{
            private String address = "hangzhou";
            private String email = "120";
            public void show2(){
                //访问外部类属性
                System.out.println(part.this.age);
                System.out.println(part.this.name);
                //访问内部类属性
                System.out.println(this.address);
                System.out.println(this.email);
                //调用局部变量
                //在JDK1.7之前,变量必须加上final,JDK1.8后是自动添加的
                System.out.println(address);
            }
        }
        Inner inner = new Inner();
        inner.show2();
    }
}

局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的声明周期与自身相同,需要将变量修饰为final

   final String address="sz";

匿名内部类

  • 没有类名的局部内部类(一切特征都与局部内部类相同)
  • 必须继承一个父类或者实现一个接口
public class TestUsb {
    public static void main(String[] args) {
        //使用匿名内部类
        //定义类、实现类、创建对象的语法合并,只能创建一个该类的对象。

        Usb usb = new Usb() {
            @Override
            public void Service() {
                System.out.println("开始旋转");
            }
        };
        usb.Service();
    }
}

优点:减少代码量

缺点:可读性太差

以下是不用匿名内部类的样子

public class TestUsb {
    public static void main(String[] args) {
        //创建接口类型的变量
        Usb usb = new Mouse();
        usb.Service();
        局部内部类
        class Fan implements Usb{

            @Override
            public void Service() {
                System.out.println("连接电脑成功!");
            }
        }
        //使用局部内部类开始创建对象
        Usb usb = new Fan();
        usb.Service();      
    }
}
public interface Usb {
    void Service();
}
public class Mouse implements Usb{
    @Override
    public void Service() {}
}

Object类

Object又叫超类、基类,所有类的直接或间接父类,位于继承树的最顶层,任何类,如没有书写extends显示继承某个类,都默认直接继承Object类,否则为间接继承,Object类中所定义的方法,是所有对象都具备的方法

Object类型可以存储任何对象

  • 作为参数,可以接受任何对象

  • 作为返回值,可返回任何对象

getClass()方法

定义: public final Class <T> getClass(){}
作用:返回引用中存储的实际对象类型,通常判断两个引用中实际 存储对象类型是否一致。
public class TestStudent {
    public static void main(String[] args) {
        Student s1 = new Student("li",11);
        Student s2 = new Student("wang",23);
        //判断S1和S2是否是同意类型
        Class class1 = s1.getClass();
        Class class2 = s2.getClass();
        if (class1==class2){
            System.out.println("same");
        }else {
            System.out.println("no same");
        }
    }
}

hashCode()方法

定义:public int hashCode(){}
作用:返回该对象的哈希码值,哈希值根据对象的地址或字符串或数字使用hash算法计算出来的int类型的数值
package commonclass.getclas;

public class TestStudent {
    public static void main(String[] args) {
        Student s1 = new Student("li",11);
        Student s2 = new Student("li",11);
        //打印哈希值
        System.out.println("====================");
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());

		//赋值给到新的变量时,哈希值也会被赋值过去
        Student s3 = s1;
        System.out.println(s3.hashCode());
        System.out.println("====================");
    }
}

输出

====================
1956725890
356573597
1956725890
====================

toString()方法

定义:public boolean equals(Object obj){}
作用:比较两个对象的内容是否相同

思考:equals未重写时,比较的是内容还是内存地址?

equal是object类的方法,所有没有重写这个类的方法;比较的都是内存地址,和==是一样的,重写后该方法是按照重写的方法来进行比较,比如String类就重写了这个方法,比较的是内容。

如何将equals()方法进行覆盖?

  1. 比较两个引用是否指向同一个对象

  2. 判断obj是否为null

  3. 判断两个引用指向的实际对象类型是否一致、

  4. 强制类型转换

  5. 依次比较各个属性值是否相同。

    @Override
    public boolean equals(Object o) {
        //1、判断两个对象是否是同一引用
        if (this==o){
            return true;
        }
        //2、判断o是否为null
        if (o==null){
            return false;
        }
        //3、判断是否是同一类型
        //第一种
//        if(this.getClass()==o.getClass()){
//
//        }
        //第二种
        if(o instanceof Student){
            //4、强制类型转换
            Student s=(Student) o;
            //5、比较各个属性值是否相同
            if (this.name.equals(s.getName())&&this.age==s.getAge()){
                return true;
            }
         }
        return false;
    }

这是手写的,可能存在bug,可以直接使用idea的快捷键alt+insert自动重写equals

finalize()方法

作用:当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列。

思考:什么样的对象会被判定为垃圾对象?

public class TestStudent2 {
    public static void main(String[] args) {
        //已经有指定的,无法直接回收
//        Student s1 = new Student("a",1);
//        Student s2 = new Student("b",1);

        //无指定
        new Student("c",1);
        new Student("d",1);
        //垃圾回收
        System.gc();
        System.out.println("已回收");
    }
}

//重写finalize方法
    @Override
    protected void finalize() throws Throwable {
        System.out.println(this.name+"销毁");
    }

垃圾对象:没有有效引用指向此对象时,为垃圾对象。

垃圾回收:由GC销毁垃圾对象,释放数据内存空间

自动回收机制:JVM的内存耗尽,一次性回收所有垃圾对象。

手动回收机制:使用System.gc();通知JVM执行垃圾回收。

包装类

什么是包装类?

基本数据类型所对应的引用数据类型

装箱和拆箱

基本数据类型存储在栈中,引用数据类型是存储在堆中

将栈中的数据放到堆中,就是装箱

将堆中的对象放到栈中,就是拆箱

//自动装箱和拆箱
public class Demo01 {
    public static void main(String[] args) {
        //JDK1.5之前的写法
        //装箱操作、基本类型转换引用类型
        int num1 = 100;
        //使用Integer创建对象,装箱的两种方法
        Integer integer1 = new Integer(num1);
        Integer integer2 = Integer.valueOf(num1);
        System.out.println("装箱");
        System.out.println(integer1);
        System.out.println(integer2);
        //拆箱操作、引用类型转换基本类型
        Integer integer3 = new Integer(100);
        int num2 = integer3.intValue();
        System.out.println(num2);
        System.out.println("===================");
        //JDK1.5之后的写法
        //java提供了自动装箱和拆箱
        //自动装箱
        int age = 200;
        Integer integer4 = age;
        System.out.println(integer4);
        //自动拆箱
        int num3 = integer4;
        System.out.println(num3);
    }
}

基本类型和字符串转换

8中包装类提供不同类型间的转换方式:

Number父类提供的6个共性方法

parseXXX()静态方法---将字符串转换成基本类型

valueOf静态方法---装箱操作,基本类型转换成引用类型

注意:需保证类型兼容,否则容易抛出NumberFormatException异常

//字符串与基本类型的转换
//基本类型转换成字符串
int n1 = 20;
//1、使用+
String s1 = n1+"";
//2使用Integer的toString()方法
//radix转换的进制
String s2 = Integer.toString(n1,16);
System.out.println(s1);
System.out.println(s2);

//字符串转换成基本类型
String str = "100";
//使用Integer的parseXXX方法
int n2 = Integer.parseInt(str);
System.out.println(n2);

//boolean字符串转换成基本类型
String str2 = "true";
boolean b1 = Boolean.parseBoolean(str2);
System.out.println(str2);

Interger缓冲区

Java预先创建了256个常用的整数包装类型对象;在实际应用中,对已创建的对象进行复用。

//关于Integer缓冲区的面试题
public class Demo02 {
    public static void main(String[] args) {

        //思考?是否相等
        //不相等,==比较的是内存地址,
        // Integer是引用类型在堆中,所以内存地址不同
        Integer integer1 = new Integer(20);
        Integer integer2 = new Integer(20);
        System.out.println(integer1==integer2);

        //思考?是否相等
        //相等,相当于自动装箱
        //实际完整代码:Integer integer3 = Integer.valueOf(30);
        //对于valueOf是有在堆中提前设计的缓存区间,可以存储-128-127之间的数字
        Integer integer3 = 30;
        Integer integer4 = 30;
        System.out.println(integer3==integer4);

        //思考?是否相等
        //不相等。当范围超出设计的缓存区间,会自动另外开辟新的空间,则为false
        Integer integer5 = 300;
        Integer integer6 = 300;
        System.out.println(integer5==integer6);

    }
}

String类

字符串是常量,创建之后不可改变;字符串字面存储在字符串池中,可以共享。

String s1 = "Hello";产生一个对象,字符串池中存储

String s2 = new String("Hello");产生两个对象,堆,池各存储一个

public class Demo03 {
    public static void main(String[] args) {
       //注意这里修改的不是s1,而是在常量池中重新开辟了一个空间,叫wang
        //s1也指向wang
        String s1 = "lee";
        s1 = "Wang";

        //面试题
        //思考:为什么是false?
        //new是在堆中开辟新的空间,同时又指向常量池,相当于两个地址
        //==比较的是内存地址,所以返回false
        String s2 = new String("Zhang");
        String s3 = new String("Zhang");
        System.out.println(s2==s3);
    }
}

常用方法

//String方法
//1、length;返回字符串长度
//2、CharAt;返回某个位置的字符
//3、contain;判断是否包含某个子字符串
String str1 = "王冰冰最美";
System.out.println(str1.length());
System.out.println(str1.charAt(str1.length()-1));
System.out.println(str1.contains("王"));

//4、toCharArray;返回字符串对应的数组
//5、iNdexOf;返回子字符串首次出现的位置
//6、lastIndexOf;返回字符串最后一次出现的位置
System.out.println(Arrays.toString(str1.toCharArray()));
System.out.println(str1.indexOf("冰"));
System.out.println(str1.lastIndexOf("冰"));

//7、trim();去电字符串前面的空格
//8、toUpperCase()/toLowerCase();把小写转换成大写,大写转小写
//9、endWith()/startsWith();是否是以str结尾;或开头
String str2 = " wangbingBingzuimei ";
System.out.println(str2.trim());
System.out.println(str2.toUpperCase());
System.out.println(str2.toLowerCase());
String str3 = "wangbingbing";
System.out.println(str3.endsWith("bing"));
System.out.println(str3.startsWith("wang"));

//10、replace();用新的字符串替换旧的字符或字符串
//11、split();对字符串拆分
String str4 = "[wangbingbing shi ,zui mei de]";
System.out.println(str4.replace("wang","li"));

//加上[] 意味着,可以同时分离空格和逗号(正则表达式)
//+ 意味着出现多个空格和逗号都可以去除
String[] arr = str4.split("[ ,]+");
System.out.println(arr.length);
for (String s:arr
     ) {
    System.out.print(s);

}


//12、补充两个方法equals()、compareTo();
String str5 = "hello";
String str6 = "HELLO";
//equalsIgnoreCase()忽视字母大小进行比较
System.out.println(str5.equalsIgnoreCase(str6));

//compareTo()长度一样,依次比较的是字符
String str7 = "abc";
String str8 = "xyz";
System.out.println(str7.compareTo(str8));

//长度不一样,就比长度
String str9 = "abc";
String str10 = "abcbnm";
System.out.println(str9.compareTo(str10));

StringBuffer和StringBuilder

StringBuffer:可变长字符串,JDK1.0提供,运行效率低,线程安全,用于多线程

StringBuilder:可变长字符串,JDK1.5提供,运行效率高,线程不安全,用于单线程

/**
 * StringBuffer和StringBuilder
 * 和String区别
 * 1、效率比String更高
 * 2、比String更节省内存
 */
public class Demo04 {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer();
        //1、append()、追加
        sb.append("wangbingbing");
        System.out.println(sb);
        sb.append("zuimei");
        System.out.println(sb.toString());
        //2、insert()、插入
        sb.insert(0,"woshuo");
        System.out.println(sb.toString());
        //3、replace()、替换
        sb.replace(0,2,"ni");
        System.out.println(sb.toString());
        //4、delete()、删除
        sb.delete(0,6);
        System.out.println(sb.toString());

        sb.delete(0,sb.length());
        System.out.println(sb.length());
    }
}
/**
 * 证明StringBuilder效率高于String
 *差距是真的大
 */
public class Demo05 {
    public static void main(String[] args) {
        //开始时间
        long start = System.currentTimeMillis();
//        String string = "";
//        //String的用时
//        for (int i = 0; i < 99999; i++) {
//            string+=i;
//        }
//        System.out.println(string);

        //StringBuilder的用时
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 99999; i++) {
            sb.append(i);
        }
        System.out.println(sb);
        //结束时间
        long end = System.currentTimeMillis();
        System.out.println("用时"+(end-start));
    }
}

输出结果:

StringBuilder:用时19

StringBuffer:用时22036

BigDecimal的使用

作用:精确计算浮点数

/**
 * BigDecimal的作用
 */
public class Demo06 {
    public static void main(String[] args) {
        //思考?为什么结果不是准确的
        //double是近似值存储,不符合要求,需要借助BigDecimal
        double d1 = 1.0;
        double d2 = 0.9;
        System.out.println(d1-d2);

        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);

        //除法
        //1.4-0.5/0.9
        BigDecimal r4 = new BigDecimal("1.4")
                .subtract(new BigDecimal("0.5"))
                .divide(new BigDecimal("0.9"));
        System.out.println(r4);

        //除法涉及到的近似值
        BigDecimal r5 = new BigDecimal("10").divide(new BigDecimal("3"),3,BigDecimal.ROUND_HALF_UP);
        System.out.println(r5);
    }

}

在计算除法时

除法:.divide(new BigDecimal("3"),scal,RoundingMode mode);

参数

scal:指定小数点精确到小数点后几位

mode:指定小数部分的取舍模式,通常采用四舍五入的模式(.ROUND_HALF_UP)

Date类

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

时间单位

  • 1秒=1000毫秒

  • 1毫秒=1000微秒

  • 1微秒=1000纳秒

/**
 * Date方法
 *
 */
public class Demo07 {
    public static void main(String[] args) {
        //创建对象
        Date date1 = new Date();
        //当前时间
        System.out.println(date1.toString());
        System.out.println(date1.toLocaleString());
        //昨天时间
        Date date2 = new Date(date1.getTime()-60*60*24*1000);
        System.out.println(date2.toLocaleString());

        //方法after before
        boolean b1 = date1.after(date2);
        System.out.println(b1);
        boolean b2 = date1.before(date2);
        System.out.println(b2);

        //比较CompareTo()
        int d = date2.compareTo(date1);
        System.out.println(d);

        //比较是否相等equals()
        boolean b3 = date1.equals(date2);
        System.out.println(b3);
    }
}

Calendar类

作用:Calendar提供了获取或设置各种日历字段的方法

/**
 * Calendar类
 */
public class Demo08 {
    public static void main(String[] args) {
        //因为Calendar修饰符是protected,所以无法new
        //1、创建对象
        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);
        //HOUR_OF_DAY代表24小时制
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        //分
        int minute = calendar.get(Calendar.MINUTE);
        //秒
        int second = calendar.get(Calendar.SECOND);
        System.out.println("年" + year +
                "月" + month +
                "日" + day +
                "时" + hour +
                "分" + minute +
                "秒" + second);

        //3、set方法修改时间
        Calendar calendar1 = Calendar.getInstance();
        calendar1.set(Calendar.DAY_OF_MONTH,5);
        System.out.println(calendar1.getTime().toLocaleString());

        //4、add方法修改时间
        calendar1.add(Calendar.HOUR_OF_DAY,-1);
        System.out.println(calendar1.getTime().toLocaleString());

        //5、补充方法,查看参数的最大值
        int max = calendar1.getActualMaximum(Calendar.DAY_OF_MONTH);
        int min = calendar1.getActualMinimum(Calendar.DAY_OF_MONTH);
        System.out.println(max);
        System.out.println(min);

    }
}

SimpleDateFormat类

SimpleDateFormat是一个以语言环境有关的方式来格式化和解析日期的具体类

进行格式化(日期->文本)、解析(文本->日期)

public class Demo09 {
    public static void main(String[] args) throws ParseException {
        //1、创建SimpleDateFormat对象
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
        //创建Date
        Date date = new Date();
        //格式化date 把日期转换成字符串
        String s1 = simpleDateFormat.format(date);
        System.out.println(s1);
        //解析,格式要与simpleDateFormat规定的格式相同
            Date date1 = simpleDateFormat.parse("2002-02-02 10-11-11");
        System.out.println(date1);
    }
}

System类

system系统类,主要用于获取系统的属性数据和其他操作,构造方法私有的。

/**
 * System类
 */
public class Demo10 {
    public static void main(String[] args) {

        //1、arraycopy:数组的复制
        //src:原数组
        //srcPos:从原数组哪个位置开始复制
        //dest:目标数组
        //destPos:从目标数组的哪个位置开始粘贴
        //length:复制的长度
        int[] arr1 = {1,2,3,4,56,6};
        int[] arr2 = new int[8];
        System.arraycopy(arr1,0,arr2,0,6);

        for (int i = 0; i < arr2.length; i++) {
            System.out.println(arr2[i]);
        }

//        Arrays.copyOf();还是使用的System.arraycopy,

        //2、复制当前系统时间
        long start = System.currentTimeMillis();
        for (int i = 0; i < 99999999; i++) {
            for (int j = 0; j < 99999999; j++) {
                int result = i+j;
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("用时:"+(end-start));

        //3、建议JVM启动垃圾回收器回收垃圾
        System.gc();

        //4、退出JVM如果参数为0,正常退出,非0表示异常退出
        System.exit(0);
        System.out.println("上面喊收工了,后面就不执行了");
    }
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM