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.mzph.cn/news/799024.shtml

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

相关文章

网络安全流量平台_优缺点分析

FlowShadow(流影),Ntm(派网),Elastiflow。 Arkimesuricata,QNSMsuricata,Malcolm套件。 Malcolm套件优点:支持文件还原反病毒引擎(clamav/yara)…

IntelliJ IDEA 2024.1 更新亮点汇总:全面提升开发体验

IntelliJ IDEA 2024.1 更新亮点汇总:全面提升开发体验 文章目录 IntelliJ IDEA 2024.1 更新亮点汇总:全面提升开发体验摘要引言 IntelliJ IDEA 2024.1 的新增功能主要亮点全行代码完成 最终的支持 Java 22 功能新航站楼 贝塔编辑器中的粘滞线 人工智能助…

【SpringBoot3】SpringBoot入门

需求&#xff1a;使用 SpringBoot 开发一个web应用&#xff0c;浏览器发起请求 /hello后&#xff0c;给浏览器返回字符串 “hello world "。 步骤 ①. 创建Maven工程 ②. 导入spring-boot-stater-web起步依赖 <dependency> <groupId>org.springframework…

React18从入门到实战

文章目录 一、React环境的搭建二、项目文件的介绍&#xff08;1&#xff09;package.json&#xff0c;他是项目存放依赖包的地方&#xff0c;里面包括了一些项目核心包及下载的其他插件包&#xff08;2&#xff09;src文件夹是项目源码目录&#xff0c;平时开发页面就在其中&am…

Leetcode 581. 最短无序连续子数组

心路历程&#xff1a; 本以为这道题要用动态规划求解&#xff0c;因为题目中这几个关键字与动态规划太匹配了&#xff0c;结果想了半天也没发现dp(i)和dp(i-1)的递推关系。 这道题本意考察双指针的做法&#xff0c;也可以用排序后做比较的方式来做。 注意的点&#xff1a; 1…

修电机所需要的基本工具

等距式 模具 同心式模具 电机划线刀 压脚 千分尺 -----测量线径 钳形电流表------- 测量 空载 满载下的电流值 摇表&#xff0c; 测量线圈是否碰到外壳 指针式万用表 胶锤 整理线圈 绝缘纸和青稞纸&#xf…

服务器主机安全受到危害的严重性

为了让小伙伴们了解到服务器主机安全受到危害的严重性&#xff0c;以下详细说明一下&#xff1a;1. 数据泄露&#xff1a;如果服务器主机遭受攻击&#xff0c;攻击者可能会窃取敏感数据&#xff0c;如用户数据、商业秘密、机密文件等&#xff0c;导致数据泄露和商业机密的泄漏。…

设计模式深度解析:AI大模型下的策略模式与模板方法模式对比解析

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》《MYSQL应用》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 策略模式与模板方法模式对比解析 文章目录 &#x1f31f;引言&#x1f31f;Part 1:…

【单源最短路 图论】882. 细分图中的可到达节点

作者推荐 视频算法专题 本文涉及知识点 单源最短路 图论 LeetCode 882. 细分图中的可到达节点 给你一个无向图&#xff08;原始图&#xff09;&#xff0c;图中有 n 个节点&#xff0c;编号从 0 到 n - 1 。你决定将图中的每条边 细分 为一条节点链&#xff0c;每条边之间…

Spring Security——11,自定义权限校验方法

自定义权限校验方法 一键三连有没有捏~~ 我们也可以定义自己的权限校验方法&#xff0c;在PreAuthorize注解中使用我们的方法。 自定义一个权限检验方法&#xff1a; 在SPEL表达式中使用 ex相当于获取容器中bean的名字未ex的对象。然后再调用这个对象的 hasAuthority方法&am…

hadoop分布式计算组件

什么是计算、分布式计算&#xff1f; 计算&#xff1a;对数据进行处理&#xff0c;使用统计分析等手段得到需要的结果 分布式计算&#xff1a;多台服务器协同工作&#xff0c;共同完成一个计算任务 分布式计算常见的2种工作模式 分散->汇总(MapReduce就是这种模式)中心调…

【Linux系列】如何确定当前运行的是 RHEL 9 还是 RHEL 8?

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

物联网可视化平台

随着数字化转型的深入&#xff0c;物联网技术正在成为企业实现智能化、高效化运营的重要工具。物联网可视化平台&#xff0c;作为连接物理世界与数字世界的桥梁&#xff0c;为企业提供了直观、实时的数据展示和监控能力&#xff0c;从而在数字化转型中扮演着关键角色。 一、物…

抖音-引流私域转化模式1.0现场视频,从抖音源源不断把人加到私域,

抖音-引流私域转化模式1.0现场视频&#xff0c;从抖音源源不断把人加到私域&#xff0c;让加到私域的粉丝买单 抖音-引流私域转化模式1.0现场视频&#xff0c;从抖音源源不断把人加到私域 - 百创网-源码交易平台_网站源码_商城源码_小程序源码 课程内容&#xff1a; 01.第一…

后端nginx使用set_real_ip_from获取用户真实IP

随着nginx的迅速崛起&#xff0c;越来越多公司将apache更换成nginx. 同时也越来越多人使用nginx作为负载均衡, 并且代理前面可能还加上了CDN加速&#xff0c;但是随之也遇到一个问题&#xff1a;nginx如何获取用户的真实IP地址. 前言&#xff1a;Nginx ngx_http_realip_module…

深入理解计算机系统 家庭作业 2.96

题目出的很不好,感觉没有标准. #include <stdio.h>typedef unsigned float_bits;int float_f2i(float_bits f) {unsigned sign f >> (31);unsigned exp (f >> 23) & 0xff;unsigned frac f & 0x7fffff;unsigned add (frac & 0x3) 0x3;unsig…

Pytorch张量的数学运算:向量基础运算

文章目录 一、简单运算二、广播运算1.广播的基本规则2.广播操作的例子 三、运算函数 参考&#xff1a;与凤行 张量的数学运算是深度学习和科学计算中的基础。张量可以被视为一个多维数组&#xff0c;其在数学和物理学中有广泛的应用。这些运算包括但不限于加法、减法、乘法、除…

Vscode连接WSL2当中的jupyter

主要解决办法参考自这篇博客 1. 在WSL当中安装jupyter 这个随便找一篇博客即可&#xff0c;比如这篇&#xff0c;也可以根据现有的环境参考其它博客内容 2. 使用jupyter创建一个虚拟环境 首先激活想要添加的虚拟环境后&#xff0c;输入命令安装库: pip install ipykernel …

企业级开源路由系统VyOS-构建和使用

介绍 VyOS是一个基于Linux的企业级路由器操作系统&#xff0c;被许多公司和个人用来驱动物理网络设备&#xff0c;如路由器和防火墙。它有一个统一的命令行界面来管理其所有的网络相关功能&#xff08;和Juniper Junos操作很像&#xff09;。VyOS使用Debian GNU/Linux作为其基…

HTTP 常见的状态码以及其适用场景

是什么 HTTP状态码&#xff08;英语&#xff1a;HTTP Status Code&#xff09;&#xff0c;用以表示网页服务器超文本传输协议响应状态的3位数字代码 它由 RFC 2616规范定义的&#xff0c;并得到 RFC 2518、RFC 2817、RFC 2295、RFC 2774与 RFC 4918等规范扩展 简单来讲&#…