Java(二)面向对象进阶

目录

面向对象

多态性

向下转型

Object

equals()

toString()

clone()

finalize()

Static

 单例模式

代码块 

final

 抽象类与抽象方法(或abstract关键字)

接口

接口的多态性

接口的默认方法

内部类

成员内部类

局部内部类

枚举类

实现接口的枚举类

注解(Annotation)

 包装类

相互转换:

包装类的其它API

 包装类对象的特点

 包装类对象不可变


面向对象

多态性

 多态性,是面向对象中最重要的概念,在Java中的体现:对象的多态性:父类的引用指向子类的对象

父类类型 变量名 = 子类对象;

例如 

Father f = new Son();

 上面这种情况,当Son类重写了方法时,f会调用Son的方法

在编译时,f被认为是Father类,在运行时被认为是Son类:编译时,看左边;运行时,看右边。

多态的使用前提:① 类的继承关系 ② 方法的重写

属性不具备多态性,调f的属性一定是来自于Father,且无法访问 到Son类的属性

f也无法调用Son类特有的方法(弊端)

使用场景

现在我定义了三个类:人,男人,女人,之间存在继承关系

class person{public void eat(){System.out.println("人吃饭");}
}class man extends person {public void eat(){System.out.println("男人吃饭");}public void work(){System.out.println("男人工作");}
}class woman extends person {public void eat(){System.out.println("女人吃饭");}
}

在另外一个类中我声明了一个方法,我希望能调用不同类的eat方法:

public class test {public static void main(String[] args){test tt = new test();tt.eating(new man());//男人吃饭}public void eating(person p){p.eat();}
}

上面这种情况,方法在声明的时候,形参写的是person类,但是传入的是man类,调用的也是man类的方法,这就用到了多态

如果没有多态,就得定义三个重载eating函数了

向下转型

 类似于强制类型转换,在编译中一直认为f是Father类,那么只需要将f强制转换为man类就可以调用man类中独有的方法和属性

    public static void main(String[] args){test tt = new test();person p = new man();man m = (man)p;m.work();}

此处m和p的地址是一样的,其实相当于内存中已经加载了man和person的内容,只是在调用的时候有一些限制,现在强制转换之后可以就行调用了,用的是同一块地址

但是下面这种就不可以,因为内存中没有加载man的方法和属性

    public static void main(String[] args){test tt = new test();person p = new woman();man m = (man)p;m.work();}

 instanceof判断实例属于的类,在向下转型的时候可以先判断一下

        person p = new man();System.out.println(p instanceof person);//trueSystem.out.println(p instanceof man);//trueSystem.out.println(p instanceof woman);//true

Object

类 java.lang.Object是类层次结构的根类,即所有其它类的父类。每个类都使用 Object 作为超类。

Object类型的变量与除Object以外的任意引用数据类型的对象都存在多态引用

method(Object obj){…} //可以接收任何类作为其参数Person o = new Person();  
method(o);

Object方法:

equals()

在object类中,这个方法的作用是比较两个对象的地址是否一样

    public static void main(String[] args) throws InterruptedException {man p1 = new man();man p2 = new man();System.out.println(p1.equals(p2));//false}

 但是在某些引用数据类型上,这个方法可能被重写了,例如在String类中,它被重写为判断两个字符串内容是不是一样,类似的还有File、Date类

    public static void main(String[] args) throws InterruptedException {String s1 = "abcdefg";String s2 = "abcdefg";int[] a1 = {1,2,3,4};int[] a2 = {1,2,3,4};System.out.println(s1.equals(s2));//trueSystem.out.println(a1.equals(a2));//false}

这个和 == 的区别就是:

  • == 既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型就是比较内存地址

  • equals的话,它是属于java.lang.Object类里面的方法,如果该方法没有被重写过默认也是==;String等类的equals方法是被重写过的,而且String类在日常开发中用的比较多,久而久之,形成了equals是比较值的错误观点。

  • 具体要看自定义类里有没有重写Object的equals方法来判断。

  • 通常情况下,重写equals方法,会比较类中的相应属性是否都相等

  • ==如果两端数据类型不一样会报错

toString()

① 默认情况下,toString()返回的是“对象的运行时类型 @ 对象的hashCode值的十六进制形式"

② 在进行String与其它类型数据的连接操作时,自动调用toString()方法

③ 如果我们直接System.out.println(对象),默认会自动调用这个对象的toString()

④ 可以根据需要在用户自定义类型中重写toString()方法
如String 类重写了toString()方法,返回字符串的值。

clone()

对象的克隆,使用时有一些要求:

1、实现Cloneable接口

2、重写clone方法

3、在使用时必须使用try catch捕获异常

public class test {public static void main(String[] args){test tt = new test();man p = new man();p.name=33;try {man p2 = (man)(p.clone());System.out.println(p2.name);//33System.out.println(p2 == p);//false} catch (CloneNotSupportedException e) {e.printStackTrace();}}
}class man implements Cloneable{int age = 1;int name = 22;protected Object clone() throws CloneNotSupportedException {// TODO Auto-generated method stubreturn super.clone();}
}

注意:Object中的clone方法是浅拷贝

finalize()

  • 当对象被回收时,系统自动调用该对象的 finalize() 方法。(不是垃圾回收器调用的,是本类对象调用的)
    • 永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用。
  • 什么时候被回收:当某个对象没有任何引用时,JVM就认为这个对象是垃圾对象,就会在之后不确定的时间使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用 finalize()方法。
  • 子类可以重写该方法,目的是在对象被清理之前执行必要的清理操作。比如,在方法内断开相关连接资源。
    • 如果重写该方法,让一个新的引用变量重新引用该对象,则会重新激活对象。
  • 在JDK 9中此方法已经被标记为过时的。

 也需要在类中重写方法

public class test {public static void main(String[] args) throws InterruptedException {test tt = new test();man p = new man();p = null;System.gc(); //释放空间}
}class man implements Cloneable{protected void finalize() throws Throwable{System.out.println("对象被释放");}
}

Static

如果想让一个成员变量被类的所有实例所共享,就用static修饰即可,称为类变量(或类属性、静态变量)

静态变量:

public class test {public static void main(String[] args) throws InterruptedException {man m = new man();man m2 = new man();System.out.println(m.country);//cnSystem.out.println(m2.country);//cnm.country = "China";System.out.println(m.country);//ChinaSystem.out.println(m2.country);//China}
}
class man {static String country = "cn";
}
  • 静态变量的默认值规则和实例变量一样。

  • 静态变量值是所有对象共享。

  • 静态变量在本类中,可以在任意方法、代码块、构造器中直接使用。

  • 如果权限修饰符允许,在其他类中可以通过“类名.静态变量”直接访问,也可以通过“对象.静态变量”的方式访问(但是更推荐使用类名.静态变量的方式)。

  • 静态变量的get/set方法也静态的,当局部变量与静态变量重名时,使用“类名.静态变量”进行区分。

  • 在jdk6之前,静态变量放在方法区,jdk7之后放在堆空间

 静态方法

  • 静态方法在本类的任意方法、代码块、构造器中都可以直接被调用。
  • 只要权限修饰符允许,静态方法在其他类中可以通过“类名.静态方法“的方式调用。也可以通过”对象.静态方法“的方式调用(但是更推荐使用类名.静态方法的方式)。
  • 在static方法内部只能访问类的static修饰的属性或方法,不能访问类的非static的结构。
  • 静态方法可以被子类继承,但不能被子类重写。
  • 静态方法的调用都只看编译时类型。
  • 因为不需要实例就可以访问static方法,因此static方法内部不能有this,也不能有super。如果有重名问题,使用“类名.”进行区别。

 单例模式

所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。

如果我们要让类在一个虚拟机中只能产生一个对象,我们首先必须将类的构造器的访问权限设置为private,这样,就不能用new操作符在类的外部产生类的对象了,但在类内部仍可以产生该类的对象。因为在类的外部开始还无法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的

 第一种方式:饿汉式

public class test {public static void main(String[] args) throws InterruptedException {Singleton S1 = Singleton.getInstance();Singleton S2 = Singleton.getInstance();System.out.println(S1 == S2); // true}
}class Singleton{private Singleton(){}private static Singleton instance = new Singleton();public static Singleton getInstance(){return instance;}
}

第二种方式:懒汉式

public class test {public static void main(String[] args) throws InterruptedException {Singleton S1 = Singleton.getInstance();Singleton S2 = Singleton.getInstance();System.out.println(S1 == S2); // true}
}class Singleton{private Singleton(){}private static Singleton instance = null;public static Singleton getInstance(){if(instance == null){instance = new Singleton();return instance;}else{return instance;}}
}

饿汉式:

  • 特点:立即加载,即在使用类的时候已经将对象创建完毕。
  • 优点:实现起来简单;没有多线程安全问题。
  • 缺点:当类被加载的时候,会初始化static的实例,静态变量被创建并分配内存空间,从这以后,这个static的实例便一直占着这块内存,直到类被卸载时,静态变量被摧毁,并释放所占有的内存。因此在某些特定条件下会耗费内存

懒汉式:

  • 特点:延迟加载,即在调用静态方法时实例才被创建。
  • 优点:实现起来比较简单;当类被加载的时候,static的实例未被创建并分配内存空间,当静态方法第一次被调用时,初始化实例变量,并分配内存,因此在某些特定条件下会节约内存
  • 缺点:在多线程环境中,这种实现方法是完全错误的,线程不安全,根本不能保证单例的唯一性。

代码块 

1、代码块是在类中直接以 {} 包含的一段代码,主要功能是进行初始化

2、其修饰前缀只能是 static ,故可以分为静态代码块和非静态代码块

3、静态代码块随着 类 加载而执行,所以只会执行一次,而非静态代码块随着 对象 加载和执行,可以执行多次

public class test {public static void main(String[] args) throws InterruptedException {System.out.println(Singleton.age);//静态代码块  3System.out.println(Singleton.age);//3Singleton S1 = new Singleton();//非静态代码块Singleton S2 = new Singleton();//非静态代码块}
}class Singleton{public static int age = 3;{System.out.println("非静态代码块");}static {System.out.println("静态代码块");}
}

4、静态代码块不能调用非静态的属性和方法,非静态代码块可以 

5、执行顺序是:静态代码块>非静态代码块>构造方法 

public class test {public static void main(String[] args) throws InterruptedException {Singleton S1 = new Singleton();//3333 2222 1111}
}class Singleton{public Singleton(){System.out.println("1111");}{System.out.println("2222");}static {System.out.println("3333");}
}

6、代码块可以写多个,同类代码块之间的执行顺序按照声明的顺序

final

final:最终的,不可更改的

final修饰类

表示这个类不能被继承,没有子类。提高安全性,提高程序的可读性。

final class Eunuch{//太监类	
}
class Son extends Eunuch{//错误	
}

final修饰方法

表示这个方法不能被子类重写。

class Father{public final void method(){System.out.println("father");}
}
class Son extends Father{public void method(){//错误System.out.println("son");}
}

 final修饰变量

final修饰某个变量(成员变量或局部变量),一旦赋值,它的值就不能被修改,即常量,常量名建议使用大写字母。

如果某个成员变量用final修饰后,并且必须初始化(可以显式赋值、或在初始化块赋值、实例变量还可以在构造器中赋值)

 抽象类与抽象方法(或abstract关键字)

 随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类

我们声明一些几何图形类:圆、矩形、三角形类等,发现这些类都有共同特征:求面积、求周长。那么这些共同特征应该抽取到一个共同父类:几何图形类中。但是这些方法在父类中又无法给出具体的实现,而是应该交给子类各自具体实现。那么父类在声明这些方法时,就只有方法签名,没有方法体,我们把没有方法体的方法称为抽象方法。Java语法规定,包含抽象方法的类必须是抽象类

抽象类

[权限修饰符] abstract class 类名{}
[权限修饰符] abstract class 类名 extends 父类{}

抽象方法

抽象方法没有方法体和大括号

[其他修饰符] abstract 返回值类型 方法名([形参列表]);

1、抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。

2、抽象类中,也有构造方法,是供子类创建对象时,初始化父类成员变量使用的。

3、抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

4、抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。

5、不能用abstract修饰变量、代码块、构造器;不能用abstract修饰私有方法、静态方法、final的方法、final的类。

接口

在JDK8.0 之前,接口中只允许出现:

(1)公共的静态的常量:其中public static final可以省略

(2)公共的抽象的方法:其中public abstract可以省略

类可以实现多个接口,一定程度上弥补了单继承的局限性 

1、如果接口的实现类是非抽象类,那么必须重写接口中所有抽象方法

2、默认方法可以选择保留,也可以重写

3、接口中的静态方法不能被继承也不能被重写

public class test {public static void main(String[] args){Bird bird = new Bird();bird.fly();System.out.println(bird.MIN_SPEED);}
}
interface flyable{ //接口public static final int MIN_SPEED = 0;public abstract void fly();
}
interface eatable{int mouth = 1;void eat();
}
class Bird implements flyable,eatable{@Overridepublic void fly() {System.out.println("鸟可以飞");}@Overridepublic void eat() {System.out.println("鸟可以吃东西");}
}

接口之间是可以继承的,且可以实现多继承,子接口没有什么限制,但是接入子接口的类必须重写所有接口的方法

interface flyable{public static final int MIN_SPEED = 0;public abstract void fly();
}
interface eatable{int mouth = 1;void eat();
}interface fly_and_eat extends flyable,eatable{}

接口的多态性

实现类实现接口,类似于子类继承父类,因此,接口类型的变量与实现类的对象之间,也可以构成多态引用。通过接口类型的变量调用方法,最终执行的是你new的实现类对象实现的方法体。

类似于类的多态性:

[接口] 接口名 = new [实现类]

先定义接口和类: 


interface USB{void start();void end();
}class Computer{public void print(USB usb){ //形参是接口,但是传入实现类的对象usb.start();usb.end();}
}class Printer implements USB{@Overridepublic void start() {System.out.println("开始连接打印机");}@Overridepublic void end() {System.out.println("结束连接打印机");}
}

 有三种实现多态的方法:

public class test {public static void main(String[] args){Computer computer = new Computer();Printer printer = new Printer();//创建接口实现类的对象computer.print(printer);//创建接口实现类的匿名对象computer.print(new Printer());//创建接口匿名实现类的对象USB usb = new USB() {@Overridepublic void start() {System.out.println("开始连接U盘");}@Overridepublic void end() {System.out.println("结束连接U盘");}};computer.print(usb);}
}

接口的默认方法

接口中的方法也可以有方法体,但是需要设置为  默认:

public class test {public static void main(String[] args){Printer printer = new Printer();printer.test();}
}
interface USB{public default void test(){System.out.println("默认方法的方法体");}
}class Printer implements USB{}

此处必须声明default,不能省略,否则会认为是  抽象方法

接口冲突:

若两个接口中定义了两个一样的默认方法,而实现类同时接入两个接口,就会产生接口冲突,该实现类需要重写该方法:

interface USB{public default void test(){System.out.println("默认方法的方法体");}
}
interface USB1{public default void test(){System.out.println("默认方法的方法体——2");}
}class Printer implements USB,USB1{@Overridepublic void test() {System.out.println("方法重写");}
}

但是如果其继承的父类也有一样的方法就没有问题,因为继承父类的优先级更高

interface USB{public default void test(){System.out.println("默认方法的方法体");}
}
interface USB1{public default void test(){System.out.println("默认方法的方法体——2");}
}class machine{public void test(){System.out.println("父类方法");}
}
class Printer extends machine implements USB,USB1{}

在实现类中也可以调用分别调用接口的方法

class Printer extends machine implements USB,USB1{@Overridepublic void test() {super.test();USB.super.test();USB1.super.test();
//        父类方法
//        默认方法的方法体
//        默认方法的方法体——2}
}

内部类

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类(InnerClass),类B则称为外部类(OuterClass)

具体来说,当一个事物A的内部,还有一个部分需要一个完整的结构B进行描述,而这个内部的完整的结构B又只为外部事物A提供服务,不在其他地方单独使用,那么整个内部的完整结构B最好使用内部类。

分类:

成员内部类

public class test {public static void main(String[] args){//声明静态内部类person.man m1 = new person.man();//声明非静态内部类person p = new person();person.woman w1 = p.new woman();m1.eat();w1.eat();}
}
class person{static class man{public void eat(){System.out.println("man eat");}}class woman{public void eat(){System.out.println("woman eat");}}
}

显然静态成员内部类不能调用外部类的方法和属性

非静态成员内部类可以调用外部类的方法和属性,但是需要  person.this.xx

class person{public void showage(){System.out.println(this.age);}int age = 3;class woman{int age = 4;public void eat(){System.out.println("woman eat");}public void getage(){System.out.println(age); //4System.out.println(person.this.age);//3person.this.showage();//3}}
}

局部内部类

非匿名内部类:

public class test {public static void main(String[] args){person p = new person();eater m1 = p.get_a_man();m1.eat(); //man eatp.show_eat();//the man is eating}
}
interface eater{void eat();
}
class person{public eater get_a_man(){class man implements eater{public void eat(){System.out.println("man eat");}}return new man();}public void show_eat(){class man {public void eat(){System.out.println("the man is eating");}}new man().eat();}
}

上面写了两种情况,一种是返回了对象,一种是只有操作

对于返回对象的情况,必须要继承一个类或者接口,下面这种写法是无法调用到内部方法的:

class person{public Object get_a_man(){class man{public void eat(){System.out.println("man eat");}}return new man();}
}

匿名内部类:

 使用匿名内部类的对象直接调用方法

public class test {public static void main(String[] args){new Object(){public void say(){System.out.println("hhhh");}}.say();}
}

 通过父类或父接口的变量多态引用匿名内部类的对象

interface A{void say();
}public class test {public static void main(String[] args){A obj = new A(){public void say(){System.out.println("hhhh");}};obj.say();}
}

枚举类

枚举类型本质上也是一种类,只不过是这个类的对象是有限的、固定的几个,不能让用户随意创建。

例如星期的类,那么对象只会有7个

5.0之前,实际上就是在类内部自己定义好可能的对象,并设置为静态final对象


public class test {public static void main(String[] args){System.out.println(Season.SPRING.toString());//Season{SEASONNAME='春天', SEASONDESC='春暖花开'}}
}class Season{private final String SEASONNAME;//季节的名称private final String SEASONDESC;//季节的描述private Season(String seasonName,String seasonDesc){this.SEASONNAME = seasonName;this.SEASONDESC = seasonDesc;}public static final Season SPRING = new Season("春天", "春暖花开");public static final Season SUMMER = new Season("夏天", "夏日炎炎");public static final Season AUTUMN = new Season("秋天", "秋高气爽");public static final Season WINTER = new Season("冬天", "白雪皑皑");@Overridepublic String toString() {return "Season{" +"SEASONNAME='" + SEASONNAME + '\'' +", SEASONDESC='" + SEASONDESC + '\'' +'}';}
}

jdk5.0中,可以使用enum声明

  • 枚举类的常量对象列表必须在枚举类的首行,因为是常量,所以建议大写。
  • 列出的实例系统会自动添加 public static final 修饰。
  • 如果常量对象列表后面没有其他代码,那么“;”可以省略,否则不可以省略“;”。
  • 编译器给枚举类默认提供的是private的无参构造,如果枚举类需要的是无参构造,就不需要声明,写常量对象列表时也不用加参数
  • 如果枚举类需要的是有参构造,需要手动定义,有参构造的private可以省略,调用有参构造的方法就是在常量对象名后面加(实参列表)就可以。
  • 枚举类默认继承的是java.lang.Enum类,因此不能再继承其他的类型。
  • JDK5.0 之后switch,提供支持枚举类型,case后面可以写枚举常量名,无需添加枚举类作为限定。
public class test {public static void main(String[] args){System.out.println(SeasonEnum.SPRING.getSeasonName());}
}
enum SeasonEnum {SPRING("春天","春风又绿江南岸"),SUMMER("夏天","映日荷花别样红"),AUTUMN("秋天","秋水共长天一色"),WINTER("冬天","窗含西岭千秋雪");private final String seasonName;private final String seasonDesc;private SeasonEnum(String seasonName, String seasonDesc) {this.seasonName = seasonName;this.seasonDesc = seasonDesc;}public String getSeasonName() {return seasonName;}public String getSeasonDesc() {return seasonDesc;}
}

enum常用方法:

public class test {public static void main(String[] args){System.out.println(SeasonEnum.SUMMER);System.out.println(SeasonEnum.SPRING.name());SeasonEnum[] values = SeasonEnum.values();System.out.println(Arrays.toString(values));
//        SUMMER
//         SPRING
//[SPRING, SUMMER, AUTUMN, WINTER]SeasonEnum s1 = SeasonEnum.valueOf("AUTUMN");System.out.println(s1);//Autumn}
}

实现接口的枚举类

每个对象单独重写接口方法


interface season_desc{void show();
}
enum SeasonEnum implements season_desc{SPRING("春天","春暖花开"){public void show(){System.out.println("春天在哪里?");}},SUMMER("夏天","夏日炎炎"){public void show(){System.out.println("宁静的夏天");}},AUTUMN("秋天","秋高气爽"){public void show(){System.out.println("秋天是用来分手的季节");}},WINTER("冬天","白雪皑皑"){public void show(){System.out.println("2002年的第一场雪");}};private final String seasonName;private final String seasonDesc;private SeasonEnum(String seasonName, String seasonDesc) {this.seasonName = seasonName;this.seasonDesc = seasonDesc;}
}

注解(Annotation)

注解(Annotation)是从JDK5.0开始引入,以“@注解名”在代码中存在。例如:

@Override
@Deprecated
@SuppressWarnings(value=”unchecked”)

注解是可以被编译器或其他程序读取的。程序还可以根据注解的不同,做出相应的处理。

@author 标明开发该类模块的作者,多个作者之间使用,分割
@version 标明该类模块的版本
@see 参考转向,也就是相关主题
@since 从哪个版本开始增加的
@param 对方法中某参数的说明,如果没有参数就不能写
@return 对方法返回值的说明,如果方法的返回值类型是void就不能写
@exception 对方法可能抛出的异常进行说明 ,如果方法没有用throws显式抛出的异常就不能写

 @Override: 限定重写父类方法,该注解只能用于方法

@Deprecated: 用于表示所修饰的元素(类,方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择

@SuppressWarnings: 抑制编译器警告

 包装类

为了使得基本数据类型具备引用数据类型的相关特征

也就是把基本数据类型转换为  obj

public static void main(String[] args){int num = 520;Integer obj = new Integer(520);
}

 

相互转换:

1、将基本数据类型转换为引用数据类型

        Integer a = Integer.valueOf(10);System.out.println(a);//3Float b = Float.valueOf(12.3f);System.out.println(b);//12.3Float c = Float.valueOf("12.4f");System.out.println(c); //12.4Boolean d = Boolean.valueOf("sad");System.out.println(d);//false

2、将引用数据类型转换为基本数据类型

        Integer a = Integer.valueOf(10);System.out.println(a.intValue());Float b = Float.valueOf(12.3f);System.out.println(b.floatValue());

 3、自动转换

由于我们经常要做基本类型与包装类之间的转换,从JDK5.0 开始,基本类型与包装类的装箱、拆箱动作可以自动完成。例如:

        Integer a = 1;Float b=3.13f;Boolean c = true;int d = a;float e = b;boolean f = c;

 

包装类的其它API

数据类型的最大最小值

Integer.MAX_VALUE和Integer.MIN_VALUELong.MAX_VALUE和Long.MIN_VALUEDouble.MAX_VALUE和Double.MIN_VALUE

 字符转大小写

Character.toUpperCase('x');Character.toLowerCase('X');

 整数转进制

Integer.toBinaryString(int i) Integer.toHexString(int i)Integer.toOctalString(int i)

  比较的方法

Double.compare(double d1, double d2)Integer.compare(int x, int y)

 包装类对象的特点

Integer a = 1;
Integer b = 1;
System.out.println(a == b);//trueInteger i = 128;
Integer j = 128;
System.out.println(i == j);//falseInteger m = new Integer(1);//新new的在堆中
Integer n = 1;//这个用的是缓冲的常量对象,在方法区
System.out.println(m == n);//falseInteger x = new Integer(1);//新new的在堆中
Integer y = new Integer(1);//另一个新new的在堆中
System.out.println(x == y);//falseDouble d1 = 1.0;
Double d2 = 1.0;
System.out.println(d1==d2);//false 比较地址,没有缓存对象,每一个都是新new的
Integer i = 1000;
double j = 1000;
System.out.println(i==j);//true  会先将i自动拆箱为int,然后根据基本数据类型“自动类型转换”规则,转为double比较Integer i = 1000;
int j = 1000;
System.out.println(i==j);//true 会自动拆箱,按照基本数据类型进行比较Integer i = 1;
Double d = 1.0
System.out.println(i==d);//编译报错

 包装类对象不可变

public class TestExam {public static void main(String[] args) {int i = 1;Integer j = new Integer(2);Circle c = new Circle();change(i,j,c);System.out.println("i = " + i);//1System.out.println("j = " + j);//2System.out.println("c.radius = " + c.radius);//10.0}/** 方法的参数传递机制:* (1)基本数据类型:形参的修改完全不影响实参* (2)引用数据类型:通过形参修改对象的属性值,会影响实参的属性值* 这类Integer等包装类对象是“不可变”对象,即一旦修改,就是新对象,和实参就无关了*/public static void change(int a ,Integer b,Circle c ){a += 10;
//		b += 10;//等价于  b = new Integer(b+10);c.radius += 10;/*c = new Circle();c.radius+=10;*/}
}
class Circle{double radius;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/599850.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络安全基础之网络协议与安全威胁

OSI(OpenSystem Interconnect),即开放式系统互联。 一般都叫OSI参考模型,是ISO(国际标准化组织)组织在1985年研究的网络互联模型。 网络协议的简介: 定义:协议是网络中计算机或设备之间进行通信的一系列规则集合。 什么是规则?…

本地化部署离线开源免费语音识别API,支持多模态AI能力引擎

思通数科作为一家专注于多模态AI能力开源引擎平台,其技术产品涵盖了自然语言处理、情感分析、实体识别、图像识别与分类、OCR识别以及语音识别等多个领域。在语音识别这一细分市场,思通数科的技术产品中的音频文件转写服务有着相似的应用场景和功能特点。…

【Linux】达梦数据库安装部署(附详细图文)

目录 一、安装前的准备工作 1.检查操作系统配置 (1)获取系统位数 getconf LONG_BIT (2)查看操作系统release信息 cat /etc/system-release (3)查询系统名称 uname -a (4)查看操…

CSS - 你遇到过动画卡顿的问题吗

难度级别:中高级及以上 提问概率:70% 回答这道题,首先要说的就是,浏览器在每一帧动画里大概做了什么事情。首先浏览器会执行Javascript,或是操作DOM元素,紧接着需要对DOM元素进行样式计算,当计算完成后,就需要针对DOM元素的位置以及大小…

海外媒体宣发套餐推广8个要点解析为标题-华媒舍

在当前全球化的时代背景下,海外市场的开拓对于企业的发展至关重要。而海外媒体宣传是一种有效的推广方式,可以帮助企业在全球范围内打开市场。本文将对8个海外媒体宣发套餐的推广要点进行解析,帮助企业了解如何在海外市场进行宣传推广。 1. 媒…

自动装卸另类方案

导语 大家好,我是智能仓储物流技术研习社的社长,你的老朋友,老K。行业群 知名企业 读者福利: 👉抄底-仓储机器人-即买即用-免调试 智能制造-话题精读 1、西门子、ABB、汇川:2024中国工业数字化自动化50强 2…

LLMs时代的推荐系统

论文地址:https://arxiv.org/pdf/2307.02046.pdf 0、概述 随着电子商务和网络应用的繁荣发展,推荐系统(RecSys)已经成为我们日常生活中的重要组成部分,它们提供个性化建议,迎合用户偏好。虽然深度神经网络…

【Redis 知识储备】读写分离/主从分离架构 -- 分布系统的演进(4)

读写分离/主从分离架构 简介出现原因架构工作原理技术案例架构优缺点 简介 将数据库读写操作分散到不同的节点上, 数据库服务器搭建主从集群, 一主一从, 一主多从都可以, 数据库主机负责写操作, 从机只负责读操作 出现原因 数据库成为瓶颈, 而互联网应用一般读多写少, 数据库…

数仓开发之Flume《一》:Flume的概述及安装

目录 1. 🥙Flume概述 1.1 Flume简介 1.2 Flume的架构 1. 🧀agent介绍 2. ​Agent 主要有 3 个部分组成,Source、Channel、Sink。 🥗2.1 Source 🥗2.2 Sink 🥗2.3 Channel 3. 🧀Flume 自…

milvus search api的数据结构

search api的数据结构 此api的功能是向量相似度搜索(vector similarity search) 一个完整的search例子: 服务端collection是一个hnsw类型的索引。 import random from pymilvus import (connections,Collection, )dim 128if __name__ __main__:connections.connect(alias…

zdpdjango_argonadmin使用Django开发一个美观的后台管理系统

初始代码 安装依赖 pip install -r requirements.txt生成管理员账户 迁移模型: python manage.py makemigrations python manage.py migrate创建超级用户: python manage.py createsuperuser启动服务 python manage.py runserver浏览器访问&#xf…

es6新增set、map两种数据结构(超级详细-附加代码)

文章目录 一、Set增删改查add()delete()has()clear()遍历 二、Map增删改查sizeset()get()has()delete()clear()遍历 三、WeakSet 和 WeakMapWeakSetWeakMap 参考文献 如果要用一句来描述,我们可以说 Set是一种叫做集合的数据结构,Map是一种叫做字典的数…