16. 面向对象的第三大特性 → 多态性
1>. 面向对象的多态性指的是什么?
可以理解为一个事务的多种表现形态
extends继承 或者 implements 实现,是多态的前提[ 掌握 ]
2>.下面是多态存在的三个必要条件
①. 要有类的继承或实现关系
②. 要有子类方法对父类方法的重写
③. 父类引用指向子类对象
3>. 多态的格式与使用
代码当中体现多态性,其实就是一句话: 父类引用指向子类对象
格式:
①. 父类名称 对象名=new 子类名称();
②. 接口名称 对象名=new 实现类名称();
public class Fu { public void method(){ System.out.println("父类方法"); } } public class Zi extends Fu { public void method(){ System.out.println("子类方法"); } } public class Demo01Multi { public static void main(String[] args) { //使用多态的写法 //左侧父类的饮用,指向了右侧子类的对象 Fu obj=new Zi(); obj.method();//运行时看右边输出: 子类方法 } }
4>. 多态的好处和弊端
①. 好处:提高了程序的扩展性 [ 具体体现:定义方法的时候,使用父类型作为参数,将来在使用的时候,使用具体的子类类型参与操作 ]
②. 多态的弊端:不能使用子类的特有功能
5>. 多态中成员变量的访问特点 [ 编译看左边,运行还看左边 ]
①. 成员变量:编译看左边,运行还看左边
②. 成员方法:编译看左边,运行看右边 [ 先到子类中寻找看是否有重写的方法,要是子类中没有,会用继承对成员方法的访问特点,去父类中找 (理解) ]
为什么成员变量和成员方法的访问不一样呢?因为成员方法有重写,而成员变量没有
public class Fu { int num=10; public void showNum(){ System.out.println(num); } } public class Zi extends Fu { int num=20; int age=10; public void showNum(){ System.out.println(num); } } public class Demo01Multi { public static void main(String[] args) { Fu obj=new Zi(); System.out.println(obj.num);//父类的10 //System.out.println(obj.age);报错,没有向下找 System.out.println("===="); //obj.showNum();//子类没有覆盖重写就是父,10 obj.showNum(); //子类如果覆盖重写就是子,20 } }
6>. 多态中成员方法的使用特点 [ 编译看左边,运行还看右边 ]
在多肽的代码当中,成员方法的访问规则如下:看new的是谁,就优先用谁,没有则向上找
口诀:编译看左边,运行看右边
①. 成员变量:编译看左边,运行还看左边
②. 成员方法: 编译看左边,运行还看右边边
public class Zi extends Fu { public void showNum(){ System.out.println("父类showNum"); } public void method(){ System.out.println("子类method"); } public void methodFu(){ System.out.println("子类特有方法"); } } public class Fu { public void showNum(){ System.out.println("父类showNum"); } public void method(){ System.out.println("父类method"); } public void methodFu(){ System.out.println("父类特有方法"); } } public class Demo01Multi { public static void main(String[] args) { Fu obj=new Zi(); obj.method(); //父子都有,优先用子 obj.methodFu();//子类没有,父类有,向上找到父类 //编译看左边,左边是Fu,Fu当中没有metho堕胎dZi方法,所以编译报错 //obj.methodZi();错误写法 } }
7>. 对象的向上转型
对象的向上转型:父类名称 对象名=new 子类名称();
Animal animal=new Cat();
含义:父类引用指向子类
注意事项:向上转型一定是安全的
8>. 对象的向下转型
其实是一个还原的动作:格式:子类名称 对象名=(子类名称)父类的对象
含义:父类引用转为子类对象
注意事项:①. 必须保证对象本来创建的时候,就是猫,才能向下转型成猫
②. 如果对象创建的时候本来不是猫,现在非要向下转型成为猫,就会报错
public class Zi extends Fu { public void showNum(){ System.out.println("父类showNum"); } public void method(){ System.out.println("子类method"); } public void methodFu(){ System.out.println("子类特有方法"); } } public class Fu { public void showNum(){ System.out.println("父类showNum"); } public void method(){ System.out.println("父类method"); } public void methodFu(){ System.out.println("父类特有方法"); } } public class Demo01Multi { public static void main(String[] args) { Fu obj=new Zi(); obj.method(); //父子都有,优先用子 obj.methodFu();//子类没有,父类有,向上找到父类 //编译看左边,左边是Fu,Fu当中没有metho堕胎dZi方法,所以编译报错 //obj.methodZi();错误写法 } }
9>. instanceof
格式: 对象 instanceof 类型 : 这将会得到一个boolean 值结果,也就是判断前面的对象能不能当做后面类型的实列
public static void main(String[] args) {
Animal animal=new Cat();//本来是猫
//如果希望调用子类特有方法,需要向下转型
//判断一下父类引用animal 本来是不是Dog
if(animal instanceof Dog){
Dog dog=(Dog)animal;
dog.watchHouse();
}
if(animal instanceof Cat){
Cat cat=(Cat)animal;
cat.eatCat();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
10>. 题目中得到的新知识点
1. 多态前提条件中:
必须要有继承或者实现关系。 要有方法的重写,如果没有则没有任何意义,但是语法不会报错
2. 用多态方式创建对象时,可以使用以下三种方式:
①.父类引用指向子类对象。
②.间接父类引用指向子类对象。
③.接口类型引用指向实现类对象
3. 多态的向上转型有以下几种常见的格式:
①.父类类型 对象名 = 子类对象;
②.父类类型 对象名 = (父类类型)子类对象;
③.接口类型 对象名 = 实现类对象;
④.接口类型 对象名 = (接口类型)实现类对象;
17. 抽象
1>.抽象方法和抽象类的格式
抽象方法: 就是加上abstract关键字,然后去掉大括号,直接分号结束public abstract void method();
抽象类: 抽象方法所在类,必须是抽象类才行。 在class之前写上abstract即可 public abstract class Animal{ }
2>. 如何使用抽象类和抽象方法 [ 掌握 ]
①. 不能直接new创建抽象类对象
②. 必须用一个子类继承抽象父类
③. 子类必须覆盖重写抽象父类当中所有的抽象方法覆盖重写(实现): 子类去掉抽象方法的abstract关键字,然后补上方法体大括号
④. 创建子类对象进行使用
3>. 抽象方法和抽象类的注意事项:
①. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象
②. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的
理解: 子类的构造方法中,有默认的super(),需要访问父类构造方法 [ 重点 ]
③. 抽象类中,不一定包含抽象方法,但是抽象方法的类必定是抽象类
④. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。
除非该子类也是抽象类
18. 发红包案列
1.群主发普通红包
群主发普通红包,某群中有多名成员,群主给成员发普通红包,让成员领取
①. 群主的一笔金额,从群主余额中扣除,平均分成n等份,让成员领取
②. 成员领取红包后,保存到成员余额中
发红包的逻辑,三要素
返回值类型:ArrayList<Integer>
方法名称:send
参数列表:
1.总共发多少钱 int totalMoney 2.分成多少份:int count public ArrayList<Integer> send(int totalMoney,int count){ //方法体 } 收红包: 返回值类型:void 方法名称:receive 参数列表:ArrayList<Integer> public void receive(ArrayList<Integer> list){ //... }
19. 接口
1>. 接口概述与生活举例
接口就是一种公共的规范标准,只要符合规范标准,就可以大家通用
接口是一种引用数据类型,最重要的内容就是其中的 抽象方法
2>. 接口的定义基本格式
public interface 接口名称{ //接口的内容 }
备注:换成了关键字interface之后,编译生成的字节码文件依然是 .java→.class
如果是Java7,那么接口中可以包含的内容有:①. 常量 ②. 抽象方法
如果是Java8,还可以额外包含有:③. 默认方法 ④.静态方法
如果是Java9,还可以额外包含有:⑤.私有方法
3>. 接口的抽象方法
在任何版本的java中,接口都能定义抽象方法
public abstract 返回值类型 方法名称(参数列表);
①. 接口当中的抽象方法,修饰符必须是两个固定的关键字:public abstract
②. 这两个关键字修饰,可以选择性地省略
public interface MyInterfaceAbstract { //这是一个抽象方法 public abstract void method1(); //这是一个抽象方法 public void method2(); //这是一个抽象方法 abstract void method3(); //这是一个抽象方法 void method4(); }
4>. 接口的抽象方法使用
MyInterfaceAbstract public interface MyInterfaceAbstract { public abstract void method1(); } }
MyInterfaceAbstractImpl public class MyInterfaceAbstractImpl implements MyInterfaceAbstract{ public void method1() { System.out.println("这是method1"); }
MyInterfaceDemo public class MyInterfaceDemo { public static void main(String[] args) { //MyInterfaceAbstractImpl my=new MyInterfaceAbstractImpl(); MyInterfaceAbstract my=new MyInterfaceAbstractImpl(); my.method1(); } }
5>. 接口的默认方法
1. 接口的默认方法的定义
从Java 8 开始,接口中允许定义默认方法
格式:public default 返回值类型 方法名称(参数列表){ //方法体 }
2. 接口的默认方法的使用
InterfaceDefault public interface InterfaceDefault { public abstract void method1(); public default void method(){ System.out.println("这是一个默认的方法"); } }
public class InterfaceDefaultImpl implements InterfaceDefault { @Override public void method1() { } //2.接口的默认方法,也可以被接口实现类进行覆盖重写 public void method(){ System.out.println("接口实现类覆盖了默认方法"); } }
public class InterfaceDefaultImpl2 implements InterfaceDefault { @Override public void method1() { System.out.println("接口实现类2"); } }
public class DemoT { public static void main(String[] args) { InterfaceDefaultImpl2 interfaceDefault1=new InterfaceDefaultImpl2(); //调用默认方法,如果实现类中没有,会向上找 interfaceDefault1.method();//这是一个默认的方法 InterfaceDefault interfaceDefault2=new InterfaceDefaultImpl(); //调用默认方法,如果实现类中没有,会向上找 interfaceDefault2.method();//接口实现类覆盖了默认方法 } }
6>. 接口的静态方法
1. 接口中的静态方法的定义
从Java 8开始,接口当中允许定义静态方法
格式:public static 返回值类型 方法名称(参数列表){ //方法体 }
提示:就是将abstract 或者 default 换成 static 即可,带上方法体
2. 接口中静态方法的使用
注意:不能通过接口实现类的对象来调用接口当中的静态方法
正确用法:通过接口名称,直接调用其中的静态方法
格式: 接口名称.静态方法名(参数)
public interface InterfaceStatic { public static void methodStatic(){ System.out.println("这是一个静态方法在接口中"); } }
public class DemoStaticT { public static void main(String[] args) { /* InterfaceStatic stactic=new InterfaceStaticImpl(); 错误写法:stactic.methodStatic();*/ InterfaceStatic.methodStatic();//这是一个静态方法在接口中 } }
7>. 接口的私有方法定义
这个公共方法不应该让实现类使用,应该是私有化的,解决方案 : 从Java 9 开始,接口当中允许定义私有方法
①. 普通私有方法,解决多个默认方法之间重复代码的问题
格式 : private 返回值类型 方法名称(){ }
②. 静态私有方法: 解决多个静态方法之间重复代码的问题
public static 返回值类型 方法名称(参数列表){ //方法体 } public interface MyInterfacePrivateA { private void methodCommon(){ System.out.println("AAA"); System.out.println("BBB"); System.out.println("CCC"); } public default void methodDefault1(){ System.out.println("默认方法1"); methodCommon(); } public default void methodDefault2(){ System.out.println("默认方法2"); methodCommon(); } }
public interface MyInterfacePrivateB { private static void methodCommon(){ System.out.println("AAA"); System.out.println("BBB"); System.out.println("CCC"); } public static void methodDefault1(){ System.out.println("静态方法1"); methodCommon(); } public static void methodDefault2(){ System.out.println("静态方法2"); methodCommon(); } }
8>. 接口的常量定义和使用
接口当中也可以定义 " 成员变量 ",但是必须使用public static final 三个关键字进行修饰。从效果上看,这其实就是接口的常量
格式:public static final 数据类型 常量名称=数据值;
①. 接口当中的常量,可以用省略public static final ,注意不写照样是这样
②. 接口当中的常量,必须进行赋值,不可以修改
③.接口中常量名称,使用完全大写的字母,用下划线进行分割。[ 推荐 ]
public interface MyInterfaceConstant { //这其实就是一个常量,一旦赋值,不可以修饰 //public:是都能使用的 //static: 和对象没有关系了 //final : 不可变 public static final int NUM=10; } public class MyInterfaceConstantT { public static void main(String[] args) { System.out.println(MyInterfaceConstant.NUM);//10 } }
接口的内容小结
在Java 9 +版本中,接口的内容可以有:
1. 成员变量其实是常量:
格式:[ public ] [ staitc ] [ final ] 数据类型 常量名称=数据值;
①.常量必须进行赋值,而且一旦赋值不能改变
②.常量名称完全大写,用下划线进行分割
2. 接口中最重要的就是抽象方法
格式:[ public ] [ abstract ] 返回值类型 方法名称(参数列表);
实现类必须覆盖重写接口所有的抽象方法,除非实现类是抽象类
3. 从Java 8开始,接口里允许定义默认方法
格式: [ public ] default 返回值类型 方法名称(参数列表){ 方法体 }
注意:默认方法也可以覆盖重写
4. 从Java8 开始,接口里允许定义静态方法
格式:[ public ] staitc 返回值类型 方法名称(参数列表){ 方法体 }
注意:应该用过接口名称进行调用,不能通过实现类对象调用接口静态方法
5. 从Java 9 开始,接口里允许定义私有方法
格式:普通私有方法:private 返回值类型 方法名称(参数列表){ 方法体 }
普通私有方法:private static 返回值类型 方法名称(参数列表){ 方法体 }
注意:private的方法只有接口自己才能调用,不能被实现类或别人使用
10>. 继承父类并实现多个接口
①. 一个类的直接父类是唯一的,但是一个类可以同时实现多个接口
public class MyInterfaceImplA implements MyInterfaceA,MyInterfaceB{ }
②. 如果实现类所实现的多个接口当中,存在重复的抽象方法,那么值需要覆盖重写一次即可
③. 实现类所实现的多个接口中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写
④. 一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法
public class Fu { public void method(){ System.out.println("父类方法"); } } public interface MyInterface { public default void method(){ System.out.println("接口的默认方法"); } } public class Zi extends Fu implements MyInterface{ } public class DemoT { public static void main(String[] args) { Zi zi=new Zi(); zi.method();//父类方法 } }
11>. 接口之间的多继承 [ 掌握 ]
①. 类与类之间是单继承的,直接父类只有一个 [ class and class ] ⇢ extends
②. 类与接口之间是多实现的,一个类可以实现多个接口 [class and interface] ⇢implements
③. 接口与接口之间是多继承的 [ interface and interface ] ⇢extends
注意事项:①. 多个父接口当中的抽象方法如果重复,没关系
②. 多个接口当中的默认 方法如果重复,那么子接口必须进行默认方法的重写,而且要带着default的关键字
public interface MyInterfaceA { public abstract void methodA(); public abstract void methodCommon(); public default void methodDefault(){ System.out.println("AAA"); } } public interface MyInterfaceB { public abstract void methodB(); public abstract void methodCommon(); public default void methodDefault(){ System.out.println("BBB"); } } public interface MyInterface extends MyInterfaceA,MyInterfaceB { public abstract void method(); //2. 多个接口当中的默认 方法如果重复,那么子接口必须进行默认方法的重写,而且要带着default的关键字 default void methodDefault() { } }
接口案列 [ 掌握 ]
创建电脑对象,依次调用开机方法,使用USB设备, 关机方法 打印效果如下: 笔记本开机 连接鼠标的USB 断开鼠标的USB 连接键盘的USB 断开键盘的USB 笔记本关机 //USB public interface USB { public abstract void openDevice(); public abstract void closeDevice(); } //Mouse public class Mouse implements USB{ @Override public void openDevice() { System.out.println("连接鼠标的USB"); } @Override public void closeDevice() { System.out.println("断开鼠标的USB"); } } //keyBoarder public class keyBoarder implements USB { @Override public void openDevice() { System.out.println("连接键盘的USB"); } @Override public void closeDevice() { System.out.println("断开键盘的USB"); } } //noteCom public class noteCom { public void open(){ System.out.println("笔记本开机"); } public void close(){ System.out.println("笔记本关机"); } public void useDevice(USB usb){ usb.openDevice(); usb.closeDevice(); } } //Test public class Demo2 { public static void main(String[] args) { //笔记本 noteCom compu=new noteCom(); compu.open(); //鼠标 Mouse s=new Mouse(); compu.useDevice(s); //键盘 keyBoarder j=new keyBoarder(); compu.useDevice(j); compu.close(); } }
20. 类的成员 五→ 内部类
1>.内部类的概述
如果一个事物的内部包含了另一个事物,那么这就是一个类内部包含另一个类
2>. 分类
①.成员内部类 ②. 局部内部类(包含匿名内部类)
3>. 成员内部类
3.1. 成员内部类的定义格式:
修饰符 class 外部类名称{ 修饰符 class 内部类名称{ } }
3.2. 如何使用成员内部类?有两种方式
①. 间接方式: 在外部类的方法当中,使用内部类,然后main只是调用外部类的方法[private 推荐使用 ]
②. 直接方式:公式:[ public ]
外部类名称.内部类名称 对象名=new 外部类名称().new 内部类名称();
public class Body {//外部类 //外部类的属性 private String name; public class Heart{//成员内部类 //内部类的方法 public void beat(){ System.out.println("成员内部类心脏跳动"); //内用外,随意访问 System.out.println("我叫"+name); } } //外部类的方法 public void methodBody(){ System.out.println("外部类的方法"); //间接方式: new Heart().beat(); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
public class Demo01InnerClass { public static void main(String[] args) { Body body=new Body(); System.out.println("=========="); //通过外部类的对象,调用外部类的方法,里面间接在使用内部类Heart body.methodBody(); System.out.println("=========="); //按照公式写 Body.Heart bHeart=new Body().new Heart(); bHeart.beat(); } }
static和非static
public class TestInnerClass { public static void main(String[] args) { // 创建静态内部类的对象,可以直接通过外部类调用静态内部类的构造器 Person.Dog d = new Person.Dog(); // 创建非静态的内容类的对象,必须先创建外部类对象,通过外部类对象调用内部类的构造器 Person.Bird b =new Person().new Bird(); b.setName("洋洋"); } } class Person { String name = "小幸"; int age; // 成员内部类(非static) class Bird { String name = "小智"; int age; public Bird() { } public void setName(String name) { System.out.println(name);//洋洋 System.out.println(this.name);//小智 System.out.println(Person.this.name);//小幸 } public void info() { show(); } } // 成员内部类(静态内部类) static class Dog { } public void show() { System.out.println("我是show方法"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
4>. 内部类的同名变量访问
如果出现了重名现象,那么格式是: 外部类名称.this.外部类成员变量名 public class Outer { int num=10;//外部类的成员变量 public class Inner{ int num=20;//内部类的成员变量 public void methodInner(){ int num=30;//内部类方法的局部变量 System.out.println("内部类方法的局部变量30:"+num); System.out.println("内部类的成员变量"+this.num); System.out.println("外部类的成员变量"+Outer.this.num); } } }
public class DemoTTT5 { public static void main(String[] args) { Outer.Inner oInner=new Outer().new Inner(); oInner.methodInner(); } }
5>. 局部内部类
5.1. 局部内部类概述
如果一个类定义在一个方法内部的,那么这就是一个局部内部类
“局部”:只有当前属性的方法才能使用它,出了这个方法外面就不能用了
5.2. 定义格式:
修饰符 class 外部类名称{ 修饰符 返回值类型 外部类方法名称(参数列表){ class 局部内部类名称{ //.... } } }
//
public class OuterT { public void methodOuter(){ //局部内部类 class Inner{ int num=10; public void methodInner(){ System.out.println(num); } } //在这里调用 Inner inner=new Inner(); inner.methodInner(); } }
public class DemoTd { public static void main(String[] args) { OuterT obj=new OuterT(); obj.methodOuter(); } }
5.3. 小节一下类的权限修饰符
public>protect>(default)>private
定义一个类的时候,权限修饰符规则
①. 外部类:public /(default)
②. 成员内部类 : public /protect /(default) /private
③. 局部内部类: 什么都不能写
5.4. 局部内部类的final问题
局部内部类:如果希望访问所在方法的局部变量,那么这个局部变量必须是 有效的final的
备注:从java 8+开始,只要局部变量保持不变,那么final关键字可以省略
原因
①. new出来的对象在堆内存当中
②. 局部变量是跟着方法走的,在栈内存当中
③. 方法运行结束之后,立刻出栈,局部变量就会立刻消失
④. 但是new出来的对象会持续存在,知道垃圾回收消失
public class MyOuter { public static void main(String[] args) { MyOuter myOuter=new MyOuter(); myOuter.methodOuter(); } public void methodOuter(){ int i=10; class Inner{ public void innerMethod(){ System.out.println("ddd"+i); } } Inner inner1=new Inner(); inner1.innerMethod(); } }
6>. 匿名内部类 [重点掌握]
本质是: 是一个继承了该类 或者 实现了该接口的 子类匿名对象
前提:有一个类/接口,同时该类/接口 ,有且只有一个抽象方法 [ 多个抽象方法也可以,但是这样就没意义了 ]
6.1. 匿名内部类的概述
如果接口的实现类 (或者父类的子类) 只需要使用唯一的一次
那么这种情况就可以省略掉该类的定义,而改为使用[匿名内部类]
匿名内部类的定义格式:
接口名称 对象名=new 接口名称 ( ){ }; public interface MyInterface { void method();//抽象方法 } //需求:请创建接口的对象,然后调用接口的方法 public class DemoMain { public static void main(String[] args) { /* MyInterface obj=new MyInterfaceImpl(); obj.method();*/ //使用匿名内部类,这得到的是对象 MyInterface obj=new MyInterface() { public void method() { System.out.println("使用匿名内部类实现了方法1"); } }; //对象调用里面的方法 obj.method(); } }
6.2. 对格式"new 接口名称(){…}"进行解析:
①. new代表创建对象的动作
②. 接口名称就是匿名内部类需要实现哪个接口
③. {…}这才是匿名内部类的内容
6.3. 注意几点问题
①. 匿名内部类,在创建对象的时候,只能使用唯一的一次。如果希望多次创建对象,而且类的内容一样的话,那么就必须使用单独定义的实现类了
②. 匿名对象在调用方法的时候只能调用唯一一次,如果希望同一对象调用多个方法,那么必须给对象起个名字
③. 匿名内部类是省略了 [ 实现类/子类名称],但是匿名对象是省略了 [ 对象名称 ],强调:匿名内部类和匿名对象不是一回事
题目
第一题:分析以下需求,并用代码实现
interface Inter { void show(); } class Outer { //补齐代码 public void method(){ new Inter(){ public void show(){ System.out.println("HelloWorld"); } }; } } public class OuterDemo { public static void main(String[] args) { Outer.method().show(); } } 要求在控制台输出”HelloWorld”
21. 基本类型包装类
1>.包装类的概述
将基本数据类型封装成对象的好处在于对象中定义更多的功能方法操作该数据
常见的操作:用于基本数据类型和字符串之间的转换
基本类和包装类之间的对应关系 [ 掌握 ]
2>. Integer的概述和使用
1.构造方法
public Integer(int value):根据int值创建Integer对象
public Integer(String str):根据String值创建Integer对象
2.静态方法获取对象
public static Integer valueOf(int i):返回一个指定的int值的Integer的实例 public static Integer valueOf(String s):返回一个保存指定值的Integer对象String [ s如果不是数字,就会报错NumberFormatException ] //Integer i1=Integer.valueOf(11);-->Integer I2=new Integer(11) /* public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } * */ Integer i1=Integer.valueOf(11); System.out.println(i1);//11 Integer i2=Integer.valueOf("11"); System.out.println(i2);//11
3>. Integer 包装类
1. int →String
①. 和" "进行拼接
②. public static String valueOf(int i):返回int参数的字符串表示形式,该方法是String类中的对象
//①.和" "进行拼接 int i=100; String s1=i+""; System.out.println("字符串进行拼接:"+s1); //②. public static String valueOf(int i); String s2=String.valueOf(i); System.out.println("public static String valueOf(int i):"+s2);
2. String → int
①.parseInt: 基本数据类型包装类有8种,其中七种都有parseXXX()方法,可以将这七种的字符串表现形式转化成基本数据类型
char的包装类 Character中没有pareseXXX()的方法,字符串转换成String 可以通过toCharA rray()
②.String ⇢ Integer ⇢ int [ 了解 ]
//①. String--->Integer----->i //Integer i1=new Integer(s);过时了 Integer i2=Integer.valueOf(s); int x = i1.intValue(); System.out.println(x); //②. 将String转成int [推荐使用] //public static int parseInt(String str):该方法是Integer中的 int num=Integer.parseInt("123"); System.out.println(num); String str2="true"; boolean b=Boolean.parseBoolean(str2); System.out.println(b); String str="as"; char[]ch=str.toCharArray(); for(char obj:ch){ System.out.print(obj); }
4>. JDK5 的新特性自动装箱和拆箱
①. 自动装箱:把基本数据类型转换成包装类型
②. 自动拆箱:把包装类型转换为基本数据类型
注意事项: 在使用时,Integer x=null; 代码会出现NullPointerException,建议先判断是否为null,然后使用
//装箱:把基本数据类型转成对应的包装类类型 Integer i = Integer.valueOf(100); //自动装箱 : 底层也做了Integer.valueOf()这个动作 Integer i2=100; //拆箱:把包装类类型转成基本数据类型 int i3=i.intValue()+200; //自动拆箱 i2+=200; //i=i+200 自动拆箱 i=i+200 自动装箱 //注意: 在使用包装类型的时候,如果做操作,最好先判断是否为null //我们推荐是,只要是对象,在使用前就必须进行不为null的判断 Integer i4=null; if(i4!=null){ //NullPointerException[ 在这个过程中它会自动拆箱,null.intValue();会抛出异常] i4+=300; }
5>. Integer的面试题
只有自动装箱才发生这个过程,-128 – 127 是byte的取值范围,如果在这个范围内,自动装箱就不会创建对象,自动装箱就不会新创建对象;而是在常量池中获取; 如果超过了byte取值范围就会再创建对象 [ 掌握 ]
//包装类都实现了toStirng()方法和equals()方法 //-128 -- 127 是byte的取值范围,如果在这个范围内,自动装箱就不会创建对象,自动装箱就不会新创建对象; //而是在常量池中获取; 如果超过了byte取值范围就会再创建对象 Integer i3 = new Integer(1222); Integer i4 = new Integer(1222); System.out.println(i3 == i4);//false System.out.println(i3.equals(i4));//true System.out.println("------------------"); Integer i1 = 9527; Integer i2 = 9527; System.out.println(i1 == i2);//false System.out.println(i1.equals(i2));//true 这里还是比较的内容是否相等 System.out.println("------------------"); Integer i5 = 10; Integer i6 = 10; System.out.println(i5 == i6);//true System.out.println(i5.equals(i6));//true System.out.println("------------------"); Character c1 = '中'; Character c2 = '中'; System.out.println(c1 == c2);//false System.out.println(c1.equals(c2));//true System.out.println("------------------"); Character c3 = 'a'; Character c4 = 'a'; System.out.println(c3 == c4);//true System.out.println(c3.equals(c4));//true
6. 练习
字符串总数据排序 91 27 46 38 50,请写程序实现的最终输入结果是27 38 46 50 91 //1.定义一个字符串 String str="91 27 46 38 50"; //2.得到字符串中每个数据 String[]strArray=str.split(" "); //3. 定义一个int数组,把String[] 数组中每一个元素存储到int数组中 int[]arr=new int[strArray.length]; for (int i = 0; i < strArray.length; i++) { /* Integer x=Integer.valueOf(strArray[i]); arr[i]=x;//这个用到了自动拆箱*/ int x=Integer.parseInt(strArray[i]); arr[i]=x; } //4.对int进行排序 Arrays.sort(arr); //5.创建一个StringBulider进行排序 StringBuilder sb=new StringBuilder(); for (int i = 0; i < arr.length; i++) { if(i==arr.length-1){ sb.append(arr[i]); }else{ sb.append(arr[i]+" ");44 } } //6.将StringBuilder变成了String String sortStr=sb.toString(); System.out.println("sortStr = " + sortStr);