四.面向对象(二)
转载自:Java笔记目录
2.1面向对象的特征二:继承性
①引入类继承最基本的作用是:代码重用。
②语法
[修饰符列表] class 子类名 extends 父类名{ 类体; } |
③子类继承父类以后,父类中声明的属性、方法,子类就可以获取到。
明确:当父类中有私有的属性或方法时,子类同样可以获取得到,只是由于封装性的设计,使得子类不可以直接调用罢了,但是可以间接访问。子类除了通过继承,获取父类的结构之外,还可以定义自己的特有的成分。构造方法无法被子类继承。
extends:子类是对父类功能的“扩展”,明确子类不是父类的子集。
④java中类的继承性只支持单继承
一个类只能继承一个父类。反之,一个父类可以有多个子类。一个类如果没有显示的继承其他类,则该类默认继承Object,Object是SUN提供的java中的根类。
⑤子父类是相对的概念
Customer没有显示继承其他类,默认继承SUN提供的java.lang.Object;所有Customer类中也有toString方法. public class Customer{ public static void main(String[] args){ Customer c = new Customer(); String s = c.toString(); System.out.println(s); //Customer@de6ced } }
|
例子
/* 账户类 父类(超类,基类,superclass) */ public class Account{ //账号 private String actno; //余额 double balance; //Constructor Account(){} Account(String actno,double balance){ this.actno = actno; this.balance = balance; } //setter and getter public void setActno(String actno){ this.actno = actno; } public String getActno(){ return actno; } } |
/* 信用账户 子类(派生类,subclass) */ public class DebitAccount extends Account{ //信誉度 double debit; } |
public class Test03{ public static void main(String[] args){ //创建信用卡对象 DebitAccount da = new DebitAccount(); //给信用卡账号赋值 da.setActno("001"); //赋值 //可以间接访问. System.out.println(da.getActno()); //读取 //没有办法直接访问 //System.out.println(da.actno); } } |
2.2方法的重写(覆盖)(override,orverwrite)
2.2.1 什么时候方法要进行重写?
如果父类中的方法已经无法满足当前子类的业务需求,需要将父类中的方法进行重新写一遍。就是要改变父类的行为。
注意:子类如果重写父类中的方法之后,子类对象一定调用的是重写之后的方法。
2.2.2 发生方法覆盖的条件
①发生在具有继承关系的两个类之间
②必须具有相同的方法名,相同的返回值类型,相同的参数列表.
③重写的方法不能比被重写的方法拥有更低的访问权限。
④重写的方法不能比被重写的方法抛出更宽泛的异常。(异常机制再讲。)
⑤私有的方法不能被覆盖。(多态之后讲)
⑥构造方法无法被覆盖。因为构造方法无法被继承。
⑦静态的方法不存在覆盖。(多态之后讲)
⑧覆盖指的是成员方法,和成员变量无关。
继承最基本的作用:代码重用。 继承最重要的作用:方法可以重写。
2.2.3 方法的重载与重写的区别
方法重载(Overload)的条件:
①方法名称相同
②方法参数类型、个数、顺序至少有一个不同
③方法的返回类型可以不同,因为方法重载和返回类型没有任何关系
④方法的修饰符可以不同,因为方法重载和修饰符没有任何关系
⑤方法重载只出现在同一个类中
方法覆盖(Override)的条件:
①必须要有继承关系
②覆盖只能出现在子类中,如果没有继承关系,不存在覆盖,只存在重载
③在子类中被覆盖的方法,必须和父类中的方法完全一样,也就是方法名,返回类型、参数列表,完全一样
④子类方法的访问权限不能小于父类方法的访问权限
⑤子类方法不能抛出比父类方法更多的异常,但可以抛出父类方法异常的子异常
⑥父类的静态方法不能被子类覆盖
⑦父类的私有方法不能覆盖
⑧覆盖是针对成员方法,而非属性
注意:两个方法要同为static或同为非static。
public class Test01{ public static void main(String[] args){ //创建子类对象 Cat c = new Cat(); //调用方法 c.move(); Animal a = new Animal(); a.move(); } } //父类:动物 class Animal{ //成员方法 public void move(){ System.out.println("动物在移动!"); } } //子类:猫 class Cat extends Animal{ //Cat的move方法应该输出:猫在走猫步! //Animal中的move方法已经无法满足Cat了。 //所以要在Cat类中对Animal类中的move方法进行重新定义(方法的覆盖,方法的重写,Overwrite,Override) public void move(){ System.out.println("猫在走猫步!"); } } |
2.3 super关键字
①super不是引用类型,super中存储的不是内存地址,super指向的不是父类对象.
②super代表的是当前子类对象中的父类型特征。
③什么时候使用super?
类和父类中都有某个数据,例如,子类和父类中都有name这个属性。如果要再子类中访问父类中的name属性,需要使用 super.
④super可以用在什么地方?
>super可以用在成员方法中,不能用在静态方法中。
> super可以用在构造方法中。
⑤super关键字用在构造方法中:
语法:
super(实参); |
作用:通过子类的构造方法去调用父类的构造方法.
语法规则:一个构造方法第一行如果没有this(...);也没有显示的去调用super(...);系统会默认调用super();
⑥注意:
>super(...);的调用只能放在构造方法的第一行; super(....)和this(....)不能共存。super(...);调用了父类中的构造方法,但是并不一定会创建父类对象。在java语言中只要是创建java对象,那么Object中的无参数构造方法一定会执行。
>尤其当子父类出现同名成员时,可以用super进行区分;super的追溯不仅限于直接父类; super和this的用法相像,this代表本类对象的引用,super代表父类的内存空间的标识。
⑦单例模式缺点:单例模式的类型无法被继承
super用在成员方法中:
//员工 public class Employee{ String name = "张三";
//成员方法 public void work(){ System.out.println("员工在工作!"); } } |
//经理 public class Manager extends Employee{ String name = "李四"; //子类将父类中的work方法重写了. public void work(){ System.out.println("经理在工作!"); } //成员方法 public void m1(){ //this.work(); //work();
super.work();
System.out.println(this.name); System.out.println(name); System.out.println(super.name); } /* //this和super相同,都不能用在静态上下文中。 public static void m1(){ System.out.println(super.name); } */ } |
super用在构造方法中:
//账户 public class Account extends Object{ //Field private String actno; private double balance; //Constructor public Account(){ //super(); System.out.println("Account的无参数构造方法执行!"); } public Account(String actno,double balance){ //super(); this.actno = actno; this.balance = balance; } //setter and getter public void setActno(String actno){ this.actno = actno; } public String getActno(){ return actno; } public void setBalance(double balance){ this.balance = balance; } public double getBalance(){ return balance; } } |
public class DebitAccount extends Account{ //Field //独特属性 private double debit; //Constructor public DebitAccount(){ //super(); } public DebitAccount(String actno,double balance,double debit){ //通过子类的构造方法去调用父类的构造方法,作用是:给当前子类对象中的父类型特征赋值。 super(actno,balance);
this.debit = debit; } //setter and getter public void setDebit(double debit){ this.debit = debit; } public double getDebit(){ return debit; } } |
public class Test02{
public static void main(String[] args){
DebitAccount da = new DebitAccount();
} } |
单例模式的类无法被继承
//单例模式的类型没有子类。无法被继承.
//父类 public class Servlet{
//构造方法私有 private Servlet(){} } //子类 class HttpServlet extends Servlet{
} |
2.4子类对象实例化的全过程
public class TestDog { public static void main(String[] args) { Dog d = new Dog(); d.setAge(10); d.setName("小明"); d.setHostName("花花"); System.out.println("name:" + d.getName() + " age:" + d.getAge() + "hostName:" + d.getHostName()); System.out.println(d.toString()); } } //生物 class Creator { private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Creator() { super(); System.out.println("this is Creator's constructor"); } } //动物类 class Animal extends Creator { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public Animal() { super(); System.out.println("this is Animal's constructor"); } } //狗 class Dog extends Animal { private String hostName; public String getHostName() { return hostName; } public void setHostName(String hostName) { this.hostName = hostName; } public Dog() { super(); System.out.println("this is Dog's constructor"); } } |
2.5面向对象的特征三:多态性
2.5.1 关于java语言中的向上转型和向下转型
①向上转型(upcasting) : 子--->父(自动类型转换)
②向下转型(downcasting) : 父--->子(强制类型转换)
注意:无论是向上转型还是向下转型,两个类之间必须要有继承关系。
public class Animal{ //成员 public void eat(){ System.out.println("动物在吃!"); } } |
public class Cat extends Animal{ //重写 public void eat(){ System.out.println("猫吃鱼"); } //Cat特有的方法. public void move(){ System.out.println("猫走猫步!"); } } |
public class Test02{ public static void main(String[] args){ //向上转型又被称作:自动类型转换. //父类型的引用指向子类型对象. //程序分两个阶段:编译阶段,运行阶段。 //程序编译阶段只知道a1是一个Animal类型。 //程序在运行的时候堆中的实际对象是Cat类型。 Animal a1 = new Cat(); //程序在编译阶段a1被编译器看做Animal类型. //所以程序在编译阶段a1引用绑定的是Animal类中的eat方法.(静态绑定) //程序在运行的时候堆中的对象实际上是Cat类型,而Cat已经重写了eat方法。 //所以程序在运行阶段对象的绑定的方法是Cat中的eat方法.(动态绑定) a1.eat(); //猫吃鱼 //向下转型:强制类型转换 Animal a2 = new Cat(); //向上转型. //要执行move方法,怎么做? //只能强制类型转换,需要加强制类型转换符 Cat c1 = (Cat)a2; c1.move(); //判断以下程序运行的时候会出什么问题? //Animal a3 = new Dog(); //向上转型. //强制类型转换 //Cat c2 = (Cat)a3; // java.lang.ClassCastException //在做强制类型转换的时候程序是存在风险的! //为了避免ClassCastException的发生,java引入了 instanceof /* 用法: 1. instanceof运算符的运算结果是 boolean类型 2. (引用 instanceof 类型) --> true/false 例如:(a instanceof Cat) 如果结果是true表示:a引用指向堆中的java对象是Cat类型. */ Animal a3 = new Dog(); System.out.println(a3 instanceof Cat); //false //推荐:在做向下转型的时候要使用instanceof运算符判断,避免ClassCastException if(a3 instanceof Cat){ Cat c2 = (Cat)a3; } } } |
2.5.2 什么是多态
多态性,可以理解为一个事物的多种表型形态,是面向对象中最重要的概念,在java中有两种体现:
①方法的重载(overload)和重写(overwrite)。
②子类对象的多态性:并不适用于属性。调用属性是就看”.”左边的对象。可以直接应用在抽象类和接口上。
2.5.3 子类对象的多态性使用的前提
①要有类的继承
②要有子类对父类方法的重写
补充:
①程序运行分为编译状态和运行状态。
对于多态性来说,编译时,"看左边",将此引用变量理解为父类的类型;运行时,"看右边",关注于真正对象的实体:子类的对象。那么执行的方法就是子类重写的。
②Java引用变量有两个类型:编译时类型和运行时类型。
编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。若编译时类型和运行时类型不一致,就出现多态(Polymorphism)
2.5.4 对象的多态
在Java中,子类的对象可以替代父类的对象使用
①一个变量只能有一种确定的数据类型
②一个引用类型变量可能指向(引用)多种不同类型的对象
Person p = new Student(); Object o = new Person();//Object类型的变量o,指向Person类型的对象 o = new Student(); //Object类型的变量o,指向Student类型的对象 |
③子类可看做是特殊的父类,所以父类类型的引用可以指向子类的对象:向上转型(upcasting)。
④一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法。
Student m = new Student(); m.school = “pku”; //合法,Student类有school成员变量 Person e = new Student(); e.school = “pku”; //非法,Person类没有school成员变量 //属性是在编译时确定的,编译时e为Person类型,没有school成员变量,因而编译错误。 |
2.5.5 多态的好处
①使用多态可以使代码之间的耦合度降低。②项目的扩展能力增强。
例子:人喂养宠物
public class Person{//模拟主人 /* public void feed(Dog d){ //喂养 d.eat(); } public void feed(Cat c){ //因为用户的业务改变了,所以软件要升级。 c.eat(); } */ //以上的代码得出:Person类型的扩展能力太差。 //尽量不要面向具体编程,面向父类型编程,面向抽象编程 public void feed(Animal a){ a.eat(); } } |
public class Animal{ public void eat(){} } |
public class Cat extends Animal{//宠物1 public void eat(){ System.out.println("猫吃东西!"); } } |
public class Dog extends Animal{//宠物2 public void eat(){ System.out.println("狗吃东西!"); } } |
public class Test{//多态测试 public static void main(String[] args){ //1.创建主人 Person zhangsan = new Person(); //2.创建宠物 Dog d = new Dog(); Cat c = new Cat(); //3.喂 zhangsan.feed(d); zhangsan.feed(c); } } |
2.5.6 虚拟方法调用(Virtual Method Invocation)
①正常的方法调用
Person e = new Person(); e.getInfo(); Student e = new Student(); e.getInfo(); |
②虚拟方法调用(多态情况下)
Person e = new Student(); e.getInfo(); //调用Student类的getInfo()方法 |
编译时类型和运行时类型:
编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法。——动态绑定
多态小结
1.前提:
- 需要存在继承或者实现关系
- 要有覆盖操作
2.成员方法:
- 编译时:要查看引用变量所属的类中是否有所调用的方法。
- 运行时:调用实际对象所属的类中的重写方法。
3.成员变量:不具备多态性,只看引用变量所属的类。
【记忆】
虚拟方法调用:通过父类的引用指向子类的对象实体,当调用方法时,实际执行的是子类重写父类的方法。
例子:有一个舞池,规定只有人能进入,动物不能进,这时一个男人进去了,是以人的身份,但是跳舞的时候是一个男人的姿势!即调用的方法是那个实体的方法!
1)多态性的表现:①方法的重载与重写 ②子类对象的多态性
2)使用的前提:①要有继承关系 ②要有方法的重写
3)格式:
Person p = new Man();//向上转型 // 虚拟方法调用:通过父类的引用指向子类的对象实体,当调用方法时,实际执行的是子类重写父类的方法 p1.eat(); p1.walk(); // p1.entertainment(); |
4)编译时,认为p是Person类型的,故只能执行Person里才有的结构,即Man里特有的结构不能够调用。子类对象的多态性,并不使用于属性。
5)关于向下转型:
①向下转型,使用强转符:()
②为了保证不报ClassCastException,最好在向下转型前,进行判断: instanceof
// 若a是A类的实例,那么a也一定是A类的父类的实例。 // 格式: 对象a instanceof 类A:判断对象a是否是类A的一个实例.是的话,返回true;否则返回false if (p1 instanceof Woman) { System.out.println("hello!"); Woman w1 = (Woman) p1; w1.shopping(); } if (p1 instanceof Man) { Man m1 = (Man) p1; m1.entertainment(); } |
2.6 Object类
①java.lang.Object 类,是所有类的根父类!
②如果在类的声明中未使用extends 关键字指明其基类,则默认基类为Object 类
③Object类仅有一个空参的构造器 public Object(){ }
2.5.1 toString方法
SUN在Object类中设计toString方法的目的:返回java对象的字符串表示形式。
在现实的开发过程中,Object里边的toString方法已经不够用了。因为Object的toString方法实现的结果不满意。Object中的toString方法就是要被重写的。
SUN是这样实现toString方法的:
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } |
Object中的toString方法返回:类名@java对象的内存地址经过哈希算法得出的int类型值再转换成十六进制。
这个输出结果可以等同看做java对象在堆中的内存地址。
public class Test01{ public static void main(String[] args){ //创建一个Object类型的对象. Object o1 = new Object(); //调用toString方法. String oStr = o1.toString(); System.out.println(oStr); //java.lang.Object@de6ced //创建一个Person类型的对象 Person p1 = new Person("刘德华",50); //调用toString方法. String pStr = p1.toString(); System.out.println(pStr); //重写前:Person@lfb8ee3//后:Person[name=刘德华,age=50] Person p2 = new Person("巩俐",50); System.out.println(p2.toString()); //Person[name=巩俐,age=50] //print方法后面括号中如果是一个引用类型,会默认调用引用类型的toString方法. System.out.println(p2); //Person[name=巩俐,age=50] } } class Person{ String name; int age;
Person(String name,int age){ this.name = name; this.age = age; }
//重写toString方法. //根据项目的需求而定。 //需求规定,显示格式:Person[name=刘德华,age=50] public String toString(){ return "Person[name="+name+",age="+age+"]"; }
} |
【eclipse操作】
快速生成重写的toString 方法:Source à Generate toString()…
2.6.2 equals方法
Object中的equals方法:
public boolean equals(Object obj) { return (this == obj); } |
o1.equals(o2); o1是this,o2是obj
== 两边如果是引用类型,则比较内存地址,地址相同则是true,反之则false.
Object中的equals方法比较的是两个引用的内存地址。
java对象中的equals方法的设计目的:判断两个对象是否一样。
public class Test01{
public static void main(String[] args){
Object o1 = new Object(); Object o2 = new Object();
boolean b1 = o1.equals(o2);
System.out.println(b1); //false
Star s1 = new Star(100,"黄晓明"); Star s2 = new Star(100,"黄晓明"); Star s3 = new Star(110,"黄晓明");
System.out.println(s1.equals(s2)); //true System.out.println(s2.equals(s3)); //false } }
class Star{
//身份证号 int id;
//姓名 String name;
//Constructor public Star(int id,String name){ this.id = id; this.name = name; } //Object中的equals方法比较的是内存地址. //在现实的业务逻辑当中,不应该比较内存地址,应该比较内容。 //所以Object中的equals方法也要重写。 //根据需求规定重写equals方法, //需求规定:如果身份证号一致,并且名字也一致,则代表是同一个人。 //s1.equals(s2); public boolean equals(Object obj){
if(this==obj) return true;
if(obj instanceof Star){ Star s = (Star)obj; if(s.id == id && s.name.equals(name)){ return true; } }
return false; } } |
/* 关于java语言中如何比较两个字符串是否一致. 在java中比较两个字符串是否一致,不能用“==” 只能调用String类的equals方法. */ public class Test02{ public static void main(String[] args){ String s1 = new String("ABC"); String s2 = new String("ABC");
System.out.println(s1==s2); //false
//String已经重写了Object中的equals方法,比较的是内容。 System.out.println(s1.equals(s2)); //true
} } |
【eclipse快捷方式】
快速生成重写的equals 方法:
Source àGenerate hashCode() and equals()…
2.6.3 finalize方法
垃圾回收器(Garbage Collection),也叫GC,垃圾回收器主要有以下特点:
①当对象不再被程序使用时,垃圾回收器将会将其回收
②垃圾回收是在后台运行的,我们无法命令垃圾回收器马上回收资源,但是我们可以
告诉他,尽快回收资源(System.gc 和Runtime.getRuntime().gc())
③垃圾回收器在回收某个对象的时候,首先会调用该对象的finalize 方法
④GC 主要针对堆内存
⑤单例模式的缺点
finalize方法什么时候调用?
①finalize方法每个java对象都有
②finalize方法不需要程序员去调用,由系统自动调用。
③java对象如果没有更多的引用指向它,则该java对象成为垃圾数据,等待垃圾回收器的回收,垃圾回收器在回收这个java对象之前会自动调用该对象的finalize方法。
④finalize方法是该对象马上就要被回收了,例如:需要释放资源,则可以在该方法中释放。
public class Test01{ public static void main(String[] args){ Person p1 = new Person(); p1 = null; //没有引用再指向它.等待回收. //程序员只能“建议”垃圾回收器回收垃圾. System.gc(); } } class Person{ //重写Object中的finalize方法. public void finalize() throws Throwable { System.out.println(this + "马上就要被回收了!"); //让引用再次重新指向该对象,该对象不是垃圾数据,不会被垃圾回收器回收! //Person p = this; } } |
2.6.4 hashCode方法
public class Test01{
public static void main(String[] args){
//hashCode方法返回的是该对象的哈希码值 //java对象的内存地址经过哈希算法得出的int类型的数值. Test01 t = new Test01();
System.out.println(t.hashCode()); //14576877
} } |
当垃圾收集器将要收集某个垃圾对象时将会调用finalize,建议不要使用此方法,因为此方法的运行时间不确定,如果执行此方法出现错误,程序不会报告,仍然继续运行。
public class FinalizeTest01 { public static void main(String[] args) { Person person = new Person(); person.id = 1000; person.name = "张三"; //将person 设置为null 表示,person 不再执行堆中的对象 //那么此时堆中的对象就是垃圾对象 //垃圾收集(GC)就会收集此对象 //GC 不会马上收集,收集时间不确定 //但是我们可以告诉GC,马上来收集垃圾,但也不确定,会马上来,也许不会来 person = null; System.gc();//通知垃圾收集器,来收集垃圾 /* try { Thread.sleep(5000); }catch(Exception e) { } */ } } class Person{ int id; String name; //此方法垃圾收集器会调用 public void finalize() throws Throwable { System.out.println("Person.finalize()"); } } |
注意以下写法
public class FinalizeTest02 { public static void main(String[] args) { method1(); } private static void method1() { Person person = new Person(); person.id = 1000; person.name = "张三"; //这种写法没有多大的意义, //执行完成方法,所有的局部变量的生命周期全部结束 //所以堆区中的对象就变成垃圾了(因为没有引用指向对象了) //person = null; } } class Person{ int id; String name; public void finalize() throws Throwable { System.out.println("Person.finalize()"); } } |
2.7包装类(Wrapper)
基本数据类型由于不是类,不能够使用java类库里提供的大量的方法。所有在设计上,我们让每一个基本数据类型都对应一个类,同时数据存储的范围还不变。此时相当于基本数据类型就具有了类的特点。针对八种基本定义相应的引用类型—包装类(wrapper 或封装类)。有了类的特点,就可以调用类中的方法。
2.7.1 装箱
基本数据类型包装成包装类的实例 ---装箱
通过包装类的构造器实现:
int i = 500; Integer t = new Integer(i); |
还可以通过字符串参数构造包装类对象:
Float f = new Float(“4.56”); Long l = new Long(“asdf”); //NumberFormatException |
2.7.2 拆箱
获得包装类对象中包装的基本类型变量 ---拆箱
调用包装类的.xxxValue()方法:
boolean b = bObj.booleanValue(); |
JDK1.5之后,支持自动装箱,自动拆箱。但类型必须匹配。
2.7.3 字符串和基本数据类型的相互转换
①字符串转换成基本数据类型
通过包装类的构造器实现:
int i = new Integer(“12”); |
通过包装类的parseXxx(String s)静态方法:
Float f = Float.parseFloat(“12.1”); |
②基本数据类型转换成字符串
用字符串重载的valueOf()方法:
String fstr = String.valueOf(2.34f); |
更直接的方式:
String intStr = 5 + “” |
2.7.4 包装类用法举例
int i = 500; Integer t = new Integer(i); |
装箱:包装类使得一个基本数据类型的数据变成了类。
有了类的特点,可以调用类中的方法。
String s = t.toString(); // s = “500“,t是类,有toString方法 String s1 = Integer.toString(314); // s1= “314“ 将数字转换成字符串。 String s2=“4.56”; double ds=Double.parseDouble(s2); //将字符串转换成数字 |
拆箱:将数字包装类中内容变为基本数据类型。
int j = t.intValue(); // j = 500,intValue取出包装类中的数据 |
包装类在实际开发中用的最多的在于字符串变为基本数据类型。
String str1 = "30" ; String str2 = "30.3" ; int x = Integer.parseInt(str1) ; // 将字符串变为int型 float f = Float.parseFloat(str2) ; // 将字符串变为int型 |
我们需要掌握的:
基本数据类型、包装类、String类之间的转换!
简易版:
①基本数据类型与对应的包装类有自动装箱、自动拆箱
如:int i = 10; Integer i1 = i;//自动装箱 int j = i1;//自动拆箱 |
②基本数据类型、包装类---->String类:调用String类的重载的valueOf(Xxx xx);
String类---->基本数据类型、包装类:调用相应的包装的parseXxx(String str);
注意:String str = "123"; int i = (int)str;是错误的转法。 |
特别的Boolean类型的 赋值有误不会报异常,除了正确的返回true 其他一律返回false
代码:
package com.atguigu.java; import org.junit.Test; |
③基本数据类型包装类及String之间的相互转换
public class TestWrapper { //基本数据类型、包装类与String类之间的转换 @Test public void test2(){ //基本数据类型、包装类 --->String类:调用String类的重载的valueOf(Xxx x)方法 int i1 = 10; String str1 = i1 + "";//"10" Integer i2 = i1; String str2 = String.valueOf(i2); String str3 = String.valueOf(true);//"true" str2 = i2.toString(); System.out.println(str3); //String类--->基本数据类型、包装类:调用包装类的parseXxx(String str)方法 int i3 = Integer.parseInt(str2); System.out.println(i3); boolean b1 = Boolean.parseBoolean(str3); System.out.println(b1); //int i4 = (int)str2; } //基本数据类型与包装类之间的转化 @Test public void test1(){ int i = 10; System.out.println(i); boolean b = false; //基本数据类型--->对应的包装类:调用包装类的构造器 Integer i1 = new Integer(i); System.out.println(i1.toString());
Float f = new Float("12.3F"); System.out.println(f); //java.lang.NumberFormatException //i1 = new Integer("12abc"); //System.out.println(i1); //对于Boolean来讲,当形参是"true"返回true,除此之外返回false。 Boolean b1 = new Boolean("false"); System.out.println(b1);
b1 = new Boolean("truea"); System.out.println(b1);
Order o = new Order(); System.out.println("$ "+o.b);//null //包装类--->基本数据类型:调用包装类Xxx的XxxValue()方法。 int i2 = i1.intValue(); System.out.println(i2); float f1 = f.floatValue(); System.out.println(f1); boolean b2 = b1.booleanValue();
//JDK5.0以后,自动装箱和拆箱 int i4 = 12; Integer i3 = i4;//自动装箱 Boolean bb = false;
int i5 = i3;//自动拆箱 } } class Order{ Boolean b; } |
2.7.5 Junit单元测试类
【eclipse快捷键】
快速生成Junit测试类:
当前工程上鼠标右键àBuild Pathà Add Libraries… à Junit à next à 选择Junit4àfinish
import org.junit.Test;
Junit单元测试类
①当前工程下-右键build path-add libraries-Junit4
②在主类中,创建一个空参的无返回值的方法,(如:public void test1())用于代码的测试,方法上声明:@Test
③导入import org.junit.Test;
④在test1()方法中,进行代码的编写。
⑤测试:双击方法名,右键run as-junit Test即可。
public class TestJunit { public static void main(String[] args) { String str = "AA"; System.out.println(str); }
@Test public void test2(){
}
@Test public void test1(){ String str = "AA"; System.out.println(str); m1(); } public void m1(){ System.out.println("hello world"); } } |
2.7.6 包装类练习题
利用Vector代替数组处理:从键盘读入学生成绩(以负数代表输入结束),找出最高分,并输出学生成绩等级。
提示:数组一旦创建,长度就固定不变,所以在创建数组前就需要知道它的长度。而向量类java.util.Vector可以根据需要动态伸缩。
创建Vector对象:Vector v=new Vector();
给向量添加元素:v.addElement(obj); //obj必须是对象
取出向量中的元素:Object obj=v.elementAt(0);
注意第一个元素的下标是0,返回值是Object类型的。
计算向量的长度:v.size();
若与最高分相差10分内:A等;20分内:B等;30分内:C等;其它:D等
【代码】
package com.jiang.exer;
import java.util.Scanner; import java.util.Vector; public class TestScore { public static void main(String[] args) { //1.创建Scanner的对象,提示从键盘输入学生的成绩(以负数代表输入结束) Scanner s = new Scanner(System.in); System.out.println("请输入学生的成绩:(以负数代表输入结束)"); //2.for(;;),从键盘依次获取学生的成绩,并填入由Vector v=new Vector()创建的对象v中。 Vector v=new Vector(); int maxScore = 0;//记录最高分 for(;;){ int score = s.nextInt(); if(score < 0){ break; } //3.求出所有输入的正的成绩中的最高分 //获取学生成绩中的最高分 if(maxScore < score){ maxScore = score; } //依次将学生成绩村放入v中 Integer score1 = new Integer(score); v.addElement(score1); } //4.通过v.elementAt(i)依次获取填入v中的元素,同时判断一下各个分数的等级并输出。 for(int i = 0;i < v.size();i++){ Integer score = (Integer)v.elementAt(i); char level; if(maxScore - score <= 10){ level = 'A'; }else if(maxScore - score <= 20){ level = 'B'; }else if(maxScore - score <= 30){ level = 'C'; }else{ level = 'D'; } System.out.println("学生成绩为:" + score + ",等级为:" + level); } } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?