Java内部类和常用类

内部类

什么是内部类

概念

在一个类的内部再顶一个完整的类。

特点

  • 编译之后生成独立的字节码文件,会有$隔开。

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

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

成员内部类

  • 在类内定义,与实例变量方法同级别。

  • 外部类的一个实例部分,创建内部类对象时,需要依赖外部类对象。

    两种调用方法:
    //第一种
    Outer outer = new Outer();
    Inter inter = outer.new Inter();
    inter.show();
    //第二种
    Inter inter = new Outer().new Inter();
    inter.show();
    
  • 当外部类,内部类存在重名属性时,在内部类访问时会优先访问内部类属性。

    //想要在内部类中访问外部类相同属性名,可以在内部类中这样用。
    System.out.println(Outer.this.name);
    
  • 在内部类中,是不能设置静态成员,但是可以加上静态常量,加上final修饰符就可以了。

静态内部类

  • 使用static修饰

  • 可以添加任意访问修饰符(public,protected,默认,private)

  • 不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员。

  • 在静态内部类中,可以访问外部类的静态成员,但是如果想要访问外部类的非静态属性,需要在静态内部类中创建一个外部类,静态成员是通过类名来访问的。

    Outer.Innter inter = new Outer.Inner();
    inner.show();
    Outer.Inner.show();
    System.out.println(Outer.Inner.count);	//count是静态的
    
  • 只有内部类才能被修饰为静态的。

局部内部类

  • 定义在外部类方法中,作用范围和创建对象范围仅限于当前方法。
  • 局部内部类不能加任何访问修饰符。
  • 可以直接访问外部类属性,如果这个方法被修饰成静态的,那就不能直接访问外部类属性,需要创建对象。
  • 想要调用局部内部类中的成员,必须在存放局部内部类这个方法中,去创建局部内部类的对象,通过这个对象进行访问。
  • 在局部内部类中想要访问,它所处的方法中的局部变量,这个局部变量必须是常量,在jdk1.8以后就不用使用final,因为在调用的时候,就会直接转换成常量。

匿名内部类

//接口
package Third.Class;
interface Usb {
    void service();
}

//匿名内部类
package Third.Class;
public class TestUsb {
    /**@ time 2021-03-27 15:23   **/
    public static void main(String[] args) {
        // 创建接口类型的变量 
        /*
        Usb usb = new Mouse();      //类似于多态
        usb.service();
        */
        //局部内部类
        /*
        class keyboard implements Usb{
            @Override
            public void service() {
                System.out.println("连接电脑成功,键盘开始工作了");
            }
        }
        Usb usb = new keyboard();
        usb.service();
        */
        
        //基于接口的匿名内部类
        //上面那个局部内类就是用一次,就不用了,浪费了,使用匿名内部类进行优化
        //编译类型(栈):Usb接口
        //运行类型(堆):匿名内部类(相当于创建一个局部内部类)
        Usb usb = new Usb() {
            @Override
            public void service() {
                System.out.println("我是匿名内部类实现的");
            }
        };
        usb.service();
        
        //基于(抽象)类的匿名内部类
        //编译类型(栈):Father
        //运行类型(堆):匿名内部类
        //也可以作为参数进行传递
        Father father = new Father("sxy"){
            //这也可以重写父类的方法
        };
    }
}
class Father{
    public Father(String name){
        
    }
}

Object类

  • 所有类的直接或间接的父类。

getClass()方法

  • public final Class<?> getClass(){}

  • 返回引用中存储的实际对象类型。

  • 应用:通常用于判断两个引用中实际存储对象类型是否一致。

    Student s1 = new Student();
    Student s2 = new Student();
    Class class1 = s1.getClass();
    Class class2 = s2.getClass();
    if(class1==class2)	System.out.println("Yes");
    else System.out.println("No");
    

hashCode()方法

  • public int hashCode(){}

  • 返回该对像的哈希码值(对象的地址)。

  • 一般情况下相同对象返回相同哈希码。

    Student s3 = s1;
    System.out.println(s1.hashCode());
    System.out.println(s2.hashCode());
    System.out.println(s3.hashCode());
    //s1与s2地址不一样,s1和s3地址是一样的
    

toString()方法

  • public String toString(){}

  • 返回该对象的字符串表示(表现形式)

    public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    
  • 可以重写这个方法。(可以Ctrl+INS快捷操作)

    public String toString(){
        return name+":"+age;	//自己定义一个String类型的返回值
    }
    

equals()方法

  • public boolean equals(Object obj){}

    public boolean equals(Object obj){
        return (this==obj);
    }
    System.out.println(s1.equals(s2));
    
  • 默认实现为(this==obj),比较两个对象地址是否相同。

  • 可进行重写,比较两个对象的内容是否相同。

    //更详细的equals和hashCode方法的重写https://www.cnblogs.com/yuxiaole/p/9570850.html
    public boolean equals(Object obj){
        if(this==obj){
            return true;
        }
        if(obj==null){
            return false;
        }
        /*
        if(this.getClass()==obj.getClass()){}	//一般不这样用
        */
        if(obj instanceof Student){				//判断obj是不是Student的实例
            Student s = (Student)obj;			//obj传进来时是Object
            if(this.name.equals(s.getName())&&this.age==s.getAge()){	//条件根据具体来设置
                return true;
            }
        }
        return false;
    }
    

finalize()方法

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

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

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

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

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

    //类似这样的代码就是垃圾对象
    new = Student("1",2);
    new = Student("2",3);
    protected void finalize() throws Throwable { }		//jdk源码
    //重写
    protected void finalize() throws Throwable { 
        System.out.println(“垃圾正在回收”);
    }
    //在测试时这样做
    System.gc();		//系统就会自动调用finalize()进行回收垃圾
    

包装类

什么是包装类

  • 基本数据类型所对应的引用数据类型。 (基本数据类型都是放在栈里,速度快,而包装类对象的实体是存放在堆里,对象的引用存放在栈里)

  • Object可统一所有数据,包装类的默认值是null。

    boolean		Boolean
    byte		Byte
    char		Character
    short		Short
    int			Integer
    long		Long
    float		Float
    double		Double
    

类型转化与装箱,拆箱

//装箱:基本类型转成引用类型
//基本类型
int num1 = 10;	//放在栈里的
//引用类型
Integer integer1 = new Integer(num1);
Integer integer2 = Integer.valueOf(num1);

//拆箱:引用类型转成基本类型
Integer integer3 = new Integer(100);	//此时这个100是放在堆里
int num2 = integer3.intValue();

//以上方式是jdk1.5之前装箱拆箱的操作,jdk1.5之后java就提供了自动装箱和拆箱,而自动装箱拆箱就是把一些jdk1.5之前的步骤隐藏了
int age1 = 30;
//自动装箱
Integer integer4 = age;		//通过反编译是这样:Integer integer4 = Integer.valueOf(age);
//自动拆箱
int age2 = integer4;		//类比上面

基本类型和字符串之间转换

//1基本类型转成字符串
int n1 = 15;
String s1 = n1+"";	//第一种
String s2 = Integer.toString(n1);	//第二种
//String s2 = Integer.toString(n1,16);//16是16进制表示,这里可以写其他进制,例如17,18等等也可以写。

//2字符串转成基本类型
String st1 = "150";
int n2 = Integer.parseInt(st1);	//st不能是非数字字符
//boolean字符串形式转成基本类型
String st2 = "true";	//只有字符"true"会转成数字true,其他的字符都会转成数字false
boolean b1 = Boolean.parseBoolean(str2);

Integer缓冲区

public class Test {
    public static void main(String[] args) {
        Integer a = 100;
        Integer b = 100;
        Integer c = 200;
        Integer d = 200;
        System.out.println(a==b); // 打印true
        System.out.println(a==b); // 打印false
    }
}
//int IntegerCache缓存中存在着[-127,128]范围内的数就可以直接数字的封装类,但是超过这个范围就要重新new一个出来。
//Integer自动装箱的源码
public static Integer valueOf(int i) {
 if (i >= IntegerCache.low && i <= IntegerCache.high)
  return IntegerCache.cache[i + (-IntegerCache.low)];
 return new Integer(i);
}
//自动装箱和非自动装箱有什么区别?
Integer i = new Integer(1)和Integer i = 1;
1,第一种方式不会触发自动装箱的过程;而第二种方式会触发
2,在执行效率上和资源占用上的区别。第二种在一般情况下会优于第一种,但是不是绝对的,因为有可能使用的是相同的对象。

//double 处理缓存区比较困难,所以就没有,就是直接new
//源码
public static Double valueOf(double d){
    return new Double;
}

String类

字符串的存储

  • 字符串是常量,创建之后不可改变。

  • 字符串字面值存储在字符串池中,可以共享。

    String s1 = "hello";
    s1 = "world";	//此时不是修改了"hello",而是s1指向了"world"
    String s2 = "world";	//s1和s2此时指向的是常量池中同一地方
    System.out.println(s1 == s2);	//true
    
    String s3 = new String("java");	//这样的方式,一次创建两个对象。
    /*上面直接赋值型的方式,字符串对象创建在常量池中,在栈中存放着指向常量池对象的地址;而用new这种方式创建的字符串,它也会在常量池中创建一个字符串对象(如果常量池有就不会创建),但是在栈中存放的不是指向常量池对象的指针,而是在堆中创建一个对象,指向堆中的对象*/
    String s4 = new String("java");	//s3不等于s4,因为他们指向堆中不同的对象,但是在堆中不同的对象引用的是同一个常量池的字符串对象。
    //所以判断字符串是否相等,需要用equals
    System.out.println(s3.equals(s4));//false
    

常用方法

public int length();		//返回字符串的长度
public char charAt(int index);	//根据下标获取字符
public boolean contains(String str);	//判断当前字符串是否包含str
public char[] toCharArray();	//将字符串转换成数组
public int indexOf(String str);	//查找str首次出现的下标,找不到返回-1
public int indexOf(String str,int index);	//从index开始判断
public int lastIndexOf(String str);	//查找str最后一次出现的下标
public String trim();			//去掉字符串前后的空格
public String toUpperCase();	//将小写转成大写
public String toLowerCase();	//将大写转成小写
public boolean endWith(String str);	//判断字符串是否是以str结尾
public boolean startWith(String str);	//判断字符串是否以str开始
public String replace(char oldChar,char newChar);	//将旧字符或字符串替换成新的字符或字符串
public String[] split(String str);	//根据str做拆分
    String st = "java is the best and,c++ also";
    String[] arr1 = st.split(" ");	//这样是以空格分隔
    String[] arr2 = st.split("[ ,]");	//这样就可以空格和逗号一起分隔
    String[] arr2 = st.split("[ ,]+");	//如果出现两个空格在一起,就可以这样操作
public boolean equals(String str);	//比较字符串值是否相等
public boolean equalsIgnoreCase(String str); //忽略大小写的比较
public int compareTo(String str);	//返回一个差值
public String substring(int beginIndex);	//从beginIndex截取到结尾
public String substring(int beginIndex,int endIndex);	//从beginIndex截取到endIndex

StringBuffer&StringBuider

  • 可变长字符串

  • 优点比String效率高,更节省内存

    public class Application {
        public static void main(String[] args) {
            //StringBuilder和StringBuffer用法基本是一样的
            //区别StringBuilder比StringBuffer效率高一点,但是线程没有StringBuffer高
            //StringBuffer sb = new StringBuffer();
            StringBuilder sb = new StringBuilder();
            
            //1.append();字符串追加函数
            sb.append("sxy ");
            System.out.println(sb.toString());
            sb.append("love ");
            System.out.println(sb.toString());
            sb.append("syj");
            System.out.println(sb.toString());
    
            //2.insert();添加
            sb.insert(0,"5211314 ");    //insert(index,str);index是下标
            System.out.println(sb.toString());
    
            //3.replace();替换
            sb.replace(0,8,"我爱你一生一世 "); //end(最后元素的下一个)
            System.out.println(sb.toString());
    
            //delete();删除
            sb.delete(0,8); //sb.delete(0,sb.length());清空
            System.out.println(sb.toString());
    
            //reverse();翻转
            sb.reverse();
            System.out.println(sb.toString());
        }
    }
    /*
    sxy 
    sxy love 
    sxy love syj
    5211314 sxy love syj
    我爱你一生一世 sxy love syj
    sxy love syj
    jys evol yxs
    */
    

    //验证StringBuilder和String的效率
    public class Application {
        public static void main(String[] args) {
            long start = System.currentTimeMillis();
            String st = "";
            for(int i = 1; i <= 99999; i++){
                st += i;
            }
            //StringBuilder st = new StringBuilder();
            //for(int i = 1; i <= 99999; i++)st.append(i);
            long end = System.currentTimeMillis();
            
            //前者时间2371后者时间8,差距非常大
            System.out.println(end-start);
        }
    }
    

    BigDecimal

    public class Application {
        public static void main(String[] args) {
            double d1 = 1.0;
            double d2 = 0.8;
            System.out.println(d1-d2);	//输出的是0.0999999999999998
            //原因:double的存储是存它的近似值,所以在计算的时候存在误差
            //BigDecimal高精度浮点数计算
            BigDecimal b1 = new BigDecimal("1.0");
            BigDecimal b2 = new BigDecimal("0.9");
            //减法
            BigDecimal b3 = b1.subtract(b2);
            System.out.println(b3);    //0.1
            //加法
            BigDecimal b4 = b1.add(b2);
            System.out.println(b4);
            //乘法
            BigDecimal b5 = b1.multiply(b2);
            System.out.println(b5);
            //除法
            BigDecimal b6 = b1.divide(b2,10,ROUND_HALF_DOWN);   //如果出现无限循环小数,必须要表留一些位数才不会报错
            //BigDecimal b7 = b1.divide(b2);普通的
            System.out.println(b6);
        }
    }
    

    Date

public class Application {
    public static void main(String[] args) {
        //1.创建Date对象
        //今天
        Date date1 = new Date();
        System.out.println(date1.toString());
        System.out.println(date1.toLocaleString()); //有删除线说明过时了
        //昨天
        Date date2 = new Date(date1.getTime()-3600*24*1000);
        System.out.println(date2.toLocaleString());
        //2.after,before
        System.out.println(date1.after(date2)); //判断date1是否在date2后面
        System.out.println(date1.before(date2));//判断date1是否在date2前面
        //3.比较compareTo();比较毫秒值
        System.out.println(date1.compareTo(date2));
        //4.equals();
        System.out.println(date1.equals(date2));
    }
}

Calendar

public class Application {
    public static void main(String[] args) {
        //1.创建Calendar对象
        Calendar calendar = Calendar.getInstance();
        System.out.println(calendar.getTime().toLocaleString());
        //System.out.println(calendar.getTimeInMillis());//获得秒
        //2.获取时间信息
        //获取年
        int year = calendar.get(calendar.YEAR);
        //获取月   返回时是从0-11
        int month = calendar.get(calendar.MONTH)+1;
        //获取日
        int day = calendar.get(calendar.DAY_OF_MONTH);
        //获取时
        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.修改时间
        Calendar calendar2 = Calendar.getInstance();
        calendar2.set(Calendar.DAY_OF_MONTH,5);     //把时间改成第5日
        System.out.println(calendar2.getTime().toLocaleString());
        //4.add方法修改时间
        calendar2.add(Calendar.HOUR,1); //加一个小时
        System.out.println(calendar2.getTime().toLocaleString());
        //5.获得某个月的最大/小日数
        calendar2.add(Calendar.MONTH,1);
        int max = calendar2.getActualMaximum(Calendar.DAY_OF_MONTH);
        int min = calendar2.getActualMinimum(Calendar.DAY_OF_MONTH);
        System.out.println("max:"+max+"  min:"+min);
    }
}
/*
2021年4月8日 下午6:40:20
2021/4/8 18:40:20
2021年4月5日 下午6:40:20
2021年4月5日 下午7:40:20
max:31  min:1
*/

SimpleDateFormat

public class Application {
    public static void main(String[] args) throws Exception{
        //1.创建对象:y年M月d日H时m分s秒--特殊字符
        //SimpleDateFormat sp = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        SimpleDateFormat sp = new SimpleDateFormat("yyyy/MM/dd");
        //2.创建Date
        Date date = new Date();
        //格式化date(把日期转成字符串)
        String st = sp.format(date);
        System.out.println(st);
        //解析(把字符串转成时间)
        Date date1 = sp.parse("1999/11/26");    //要符合上面的格式,要抛出一个异常
        System.out.println(date1);
    }
}
/*
2021/04/08
Fri Nov 26 00:00:00 CST 1999
*/

System类

public class Application {
    public static void main(String[] args){
        //1.arraycopy;数组的复制
        //System.arraycopy(源数组,从哪个位置开始复制0,目标数组,目标数组的位置,复制长度);
        int[] arr = {10,11,12,13,14,15,16,17};
        int[] dest = new int[8];
        System.arraycopy(arr,0,dest,0,8);
        for (int i : dest) System.out.print(i+" ");
        //Arrays.copyOf();这个复制方法在源码里还是调用了System.arraycopy();
        System.out.println();

        //2.currentTimeMillis();从某个时间到现在一共过去多少秒,可以计时计算代码的执行时间
        //System.out.println(System.currentTimeMillis());
        long start = System.currentTimeMillis();
        for(int i = 0; i <= 100000; i++){
            for(int j = 0; j <= 100000; j++){
                for(int k = 0; k <= 100000; k++){
                    int s = i+j+k;
                }
            }
        }
        long end = System.currentTimeMillis();
        System.out.println(end-start);
        //3.gc();垃圾回收在上面Object类中有讲解
        //4.退出JVM
        System.exit(0);
    }
}
/*
10 11 12 13 14 15 16 17 
2551
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值