Java基础学习 day_07

常用类

内部类编译之后可生成独立的字节码文件。
内部类可以直接访问外部的属性和方法。

1。成员内部类
在类的内部定义,与实例方法和实例属性同级。
创建成员内部类,必须依赖外部对象。
创建方式:1.Outer out=new Outer();
Outer.Inner in=out.new Inner();
2.Outer.Inner in=new Outer.new Inner();
成员内部类可以使用任意的访问修饰符。
外部类的访问修饰符只能是public和默认。
成员内部类可以直接访问外部类的方法和属性。
如果成员内部类的属性和外部类的属性重名时,会优先访问内部类属性。
如果访问外部类的属性,用外部类名.this.属性
成员内部类中不能写静态属性和方法。但是可以包含静态常量(常量池中)

2.静态内部类:不依赖外部对象,直接用类名就可以访问。
级别和外部类同级别,为外部类提供功能。
创建方式:Outer.Inner in=new Outer.Inner();
访问静态内部类的静态方法:Outer.Inner.show();
特点:1.静态内部类可以使用任意访问修饰符
2.静态内部类不能直接访问外部类的实例属性和方法。但是可以直接访问外部类的静态的属性和方法。静态内部类可以有静态方法和属性。

静态的用法:静态属性、静态方法、静态内部类、静态代码块、静态导入(不太重要)。

局部内部类:定义在方法中,作用范围和创建对象仅限于当前方法中。
级别和局部变量相同。
特点:1.不能使用任何访问修饰符。
2.如果局部内部类所在方法是非静态方法,可以直接访问外部类的实例属性。如果局部内部类所在方法是静态方法,只能访问外部类的静态属性和方法,如果想访问外部类的方法和属性,可以通过创建外部对象进行访问。

//通过创建对象访问外部成员。
public static void show(){
    class Inner{
        String name="哈哈";
        public int age=12;
        public String time="昨天";
        static final int height=11;
    }
    Out out=new Out();//外部类
    System.out.println(out.name);
}

3.局部内部类可以访问局部变量。但是局部变量必须是final,在JDK1.8 可以省略。
4.局部内部类也不能声明静态方法,可以使用静态常量。

(非静态方法)访问外部类的属性和方法:外部类名.this.属性。
匿名内部类
1.匿名内部类可以使用接口,抽象类,普通类,必须要实现接口和抽象类的方法。一般都用接口。
2.匿名内部类不能手动添加构造方法,不能包含静态的成员。名字没有,怎么构造。
3.一般不包含自己特有的方法,不能直接访问,可以通过内部对象的方法。
4.匿名内部类生成的class文件:类名$编号.class
USB usb=new USB(){}

Object

查源码就可以明白,也可以根据需要进行重写。
或者查看api
任何类,如果没有书写extends显示继承某个类,都默认直接继承Object类,或则间接继承Object
Object 可以作为参数,可以接受任何对象
Object 可以作为返回值,可以返回任何对象
getClass():返回对象的类型
instanceof差不多

System.out.println(s1.getClass());//得到class 包名.类名
System.out.println(s1.getClass().getName());//得到 包名.类名
System.out.println(s1.getClass().getSimpleName());//得到 类名
System.out.println(s1.getClass().getPackage());//得到package 包名
System.out.println(s1.getClass().getPackage().getName());//得到 包名

hashCode():返回该对象的十进制的哈希码值。
哈希算法根据对象的地址或者字符串或者数字计算出来的int类型的数值。
哈希值并不唯一 可保证相同对象返回相同哈希码,尽量保证不同的对象返回不同的哈希码

toString() 返回该对象的字符串表示的形式。可以根据需求进行覆盖。比如:输出成员属性的值。
equals(obj) 比较两个引用是否指向同一个对象。String的equals()进行了重写。
重写的过程:
1.判断是不是和自己进行比较
2.判断obj是否为null
3.判断两个引用指向的实际对象类型是否一致
4.强制类型转换
5.依次比较各个属性值是否相同

//示例
public boolean equals(Object o) {
    if (this == o) return true;//地址是否相同
    if (o == null || getClass() != o.getClass()) return fals;是否为空和是否指向同一个实例对象
    Student student = (Student) o;
    return age == student.age &&
            Objects.equals(name, student.name) &&
            Objects.equals(card, student.card);
}

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

包装类

八个包装类,对应了八个基本数据类型。默认值为null
byte
short
int Integer
long Long
float Float
double Double
char Charact
boolean Boolean

Double Float 没有缓冲区

Charact 0 127
Byte Short Int Long Float -128 127
Boolean true false

自动装箱,在这个范围内,不会产生新的对象。
超出这个范围,会自动产生新的对象。

手动装箱:Integer a=new Integer(10);
手动拆箱:int b=Integer.intValue(a);
JDK5.0之后
自动装箱:int a=10; Integer b=a; //实际上是:Integer b=Integer.valueOf(a)
自动拆箱: Integer a=new Integer(10);int b=a;

基本类型和字符串之间转化
1.
int a=500;
String n1=n1+"";
2.
String s2=String.valueOf(a);
3.
String s3=Integer.toString(a);

字符串转成基本类型
1.

String s4="200";
int b=Integer.parseInt(s4);
int c=Integer.parseInt(s4,16);//16是指的进制

boolean类型的字符串转成基本类型时,只要不是ture,其他字符串都是false.
boolean a=Boolean.parseBoolean(“aaa”);

String

直接字面量赋值:String name=“张三”;name=“李四”;
字符串字面值是常量创建之后不可改变。是因为存放在方法区的常量池中,改变值,是在常量池中又开辟了新的空间,旧的就变为了垃圾。所以说创建之后不可改变。name中的地址变了,直接字面量赋值,存放的常量池的地址。
使用构造方法赋值:String name=new String(“wangwu”);
栈种存放的是堆中的地址,堆中的对象又指向常量池.

String s1="abc";
String s2="xyz";
String s3=s1+s2;//这个数据是放在堆中的

s1+s2字符串时放在堆中的,没有放在常量池中。

如果在常量池中之前已经有相同的数据,不用新建常量,直接都指向该常量池的地址。

String s1="abc";//字面量赋值在常量池中
String s2="xyz";//常量池中
String s3=s1+s2;//在堆中,s3指向堆中对象,s3存放堆中地址
String s4="abc"+"xyz";//常量池中
String s5="abcxyz";//s5和s4相同,共同指向常量池中的abcxyz
System.out.println(s3==s4);
System.out.println(s4==s5);
//答案
false
true

根据.class文件反编译如下:

在这里插入图片描述
内存分配:在这里插入图片描述

String s1="abc";
String s2="xyz";
String s3=s1+s2;
String s4=s3.intern();
String s5="abcxyz";
System.out.println(s3==s4);
System.out.println(s4==s5);

//答案
true
true

intern() 先检查常量池, 如果常量池中已经有该字符串,直接返回地址。如果没有,会把堆中的对象的地址放在常量池中,并把地址返回给他。当后来在创建相同的字符时,因为常量池中存放了地址,直接把地址返回。
在这里插入图片描述

String s1="hello";
String s2=s1.intern();
System.out.println(s1==s2);
//答案
true

特殊
//“java…”等一些关键的词已经在常量池中了。

System.out.println("---------特殊-------------");
String s1="ja";
String s2="va";
String s3=s1+s2;
String s4=s3.intern();
System.out.println(s3==s4);

//false

如果String name1=“wangwu”;

String name=new String("wangwu");
String name1="wangwu";
System.out.println(name==name1);
//答案
false

因为直接字面量赋值是存放的常量池的地址,而构造方法赋值是在堆中产生对象,再由对象指向常量池。所以地址是不同的。返回false

compareTo() 比较字符串的位置大小。前面相等,比长度。

在这里插入图片描述

可变字符串

含头不含尾

StringBuilder JDK1.5 效率高,线程不安全
StringBuffer JDK1.0 效率低,线程安全
append():追加数据
insert():插入数据
replace():替换位置
reverse():反转
delete():删除

StringBuffer str=new StringBuffer();
System.out.println("--------------append------------------");
System.out.println(str.append("abc"));
System.out.println(str.append(23));
char[] a={'a','b','c','d'};
System.out.println(str.append(a));
System.out.println(str.append(a, 0, 2));
System.out.println("--------------insert--------------------");
System.out.println(str.insert(1, "轩轩"));
System.out.println("-------------replace------------------");
System.out.println(str.replace(1, 5, "轩儿"));
System.out.println("-------------reverse------------------");
System.out.println(str.reverse());
System.out.println("-------------delete------------------");
System.out.println(str.delete(2, 5));//左闭右开
System.out.println(str.delete(0, str.length()).length());

猜你喜欢

转载自blog.csdn.net/m0_45196258/article/details/107655996