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);//true
        System.out.println(p instanceof man);//true
        System.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));//true
        System.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);//33
            System.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 stub
        return 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);//cn
        System.out.println(m2.country);//cn
        m.country = "China";
        System.out.println(m.country);//China
        System.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);//静态代码块  3
        System.out.println(Singleton.age);//3
        Singleton 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{
    @Override
    public void fly() {
        System.out.println("鸟可以飞");
    }
    @Override
    public 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{

    @Override
    public void start() {
        System.out.println("开始连接打印机");
    }
    @Override
    public 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() {
            @Override
            public void start() {
                System.out.println("开始连接U盘");
            }
            @Override
            public 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{
    @Override
    public 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{
    @Override
    public 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); //4
            System.out.println(person.this.age);//3
            person.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 eat
        p.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("冬天", "白雪皑皑");

    @Override
    public 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);//3

        Float b = Float.valueOf(12.3f);
        System.out.println(b);//12.3
        Float c = Float.valueOf("12.4f");
        System.out.println(c); //12.4

        Boolean 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_VALUE
    
Long.MAX_VALUE和Long.MIN_VALUE
    
Double.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);//true

Integer i = 128;
Integer j = 128;
System.out.println(i == j);//false

Integer m = new Integer(1);//新new的在堆中
Integer n = 1;//这个用的是缓冲的常量对象,在方法区
System.out.println(m == n);//false

Integer x = new Integer(1);//新new的在堆中
Integer y = new Integer(1);//另一个新new的在堆中
System.out.println(x == y);//false

Double 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);//1
		System.out.println("j = " + j);//2
		System.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;
}
  • 16
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值