目录
三木运算的类型转换、Integer自动装箱和new Integer(int i)的区别
面向对象特征之一:继承性
- 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可
- 减少了代码的冗余,将共性的东西提取出来作为父类,供子类使用,提高了代码的复用性
- 便于功能的扩展,子类在父类的基础上对方法进行拓展
- 为之后多态(面向对象特征之一)做准备
- 继承格式语法格式:class A extends B{} 其中:extends是延展、扩展意思
- A:子类、派生类、subclass
- B:父类、超类、基类、superclass
- 一旦子类 A 继承父类以后,子类 A 中就获取了父类 B 中声明的结构:属性、方法
- 特别的,父类中声明为 private 的属性或方法,子类继承父类以后,仍然认为获取了父类中私有的结构。 只有因为封装性的影响,使得子类不能直接调用父类的结构而已
- 子类继承父类以后,还可以声明自己特有的属性或方法,实现功能的拓展。
- 一个类可以被多个类继承(Java多重继承)
- Java 中类的单继承性:一个类只能有一个父类
- Java中类的多重继承:一个父类有一个子类、这个子类又有子类、子类的子类又有子类......(后面提及到的接口就可以实现多重继承效果)
- 子父类是相对的概念,因为继承不仅只有两代关系,可以多代
- 子类直接继承的父类,称为:直接父类。间接继承的父类,称为,间接父类。子类继承父类后,就获取了直接父类以及所有间接父类中声明的属性和方法。
- 如果我们没有显式的声明一个类的父类的话,则此类继承于 java.lang.Object 类,因此所有的 java 类(除 java.long.Object 类之外)都直接或间接地继承于 java.lang.Object 类;意味着,所有的 java 类具有 java.lang.Object 类声明的功能。
创建Person(父)类
package javase7.pojo;
public class Person {
String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println("吃饭");
sleep();
}
private void sleep() {
System.out.println("睡觉");
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
创建Student(子)类
package javase7.pojo;
public class Student extends Person{//一旦子类继承父类,就会获得父类声明的属性和方法
// String name;//子类类里继承了父类的这个属性,可以不写,也可以写,写了就是覆盖,是子类独有的和父类没有任何关系,也没有重写的意思
// int age;//子类类里继承了父类的这个属性,可以不写,也可以写,写了就是覆盖,是子类独有的和父类没有任何关系,也没有重写的意思,但是不影响继承的get/set方法
String major;//子类拓展的属性
public Student(){//子类自己的构造方法
}
public Student(String name,int age,String major){
this.name = name;//子类继承父类非private修饰的属性,因此可以调用
// this.age = age;//子类继承父类private修饰的属性,不允许直接访问
setAge(age);//只能通过从父类继承的公开的setAge()方法给age属性设置
this.major = major;
}
// public void eat(){//子类类里继承了父类的这个方法,可以不写
// System.out.println("吃饭");
// }
// @Override//异常:方法不会重写其超类中的方法
// public void sleep(){//sleep()被继承了但是被私密修饰符修饰,不能直接访问,这里写sleep()方法已经是子类独有的方法,与父类没有关系,也没有重写的意思
// System.out.println("睡觉");
// }
//子类拓展方法
public void study(){
System.out.println("学习");
}
public void show(){
System.out.println("name:" + name + ",age = " + getAge());
}
}
创建测试类
package javase7;
import javase7.pojo.Person;
import javase7.pojo.Student;
public class OOP1 {
public static void main(String[] args) {
Person p1 = new Person();
p1.eat();//吃饭睡觉
Student s1 = new Student();
s1.eat();//吃饭睡觉,使用从Person里继承回来的eat()方法
s1.show();//name:null,age = 0,子类独特的方法
s1.study();//学习,子类独特的方法
// s1.sleep();//这个方法被继承了但是却被私密了不能使用
s1.setAge(10);//因为属性被私密不能直接设置,只能通过set方法
System.out.println(s1.getAge());//10,因为属性被私密了而不能直接过去,只能通过get方法
}
}
图解
方法的重写(需要建立在继承的前提下)
- 子类继承父类以后,可以对父类中的公开的方法进行覆盖操作
- 重写以后,当创建子类对象以后,通过子类对象去调用子父类中同名同参数方法时,执行的是子类重写父类的方法。在程序执行时,子类的方法将覆盖父类的方法
- 参数列表必须完全与被重写的方法参数列表相同。
- 返回的类型必须与被重写的方法的返回类型相同(Java1.5 版本之前返回值类型必须一样,之后的 Java 版本放宽了限制,返回值类型必须小于或者等于父类方法的返回值类型)。
- 访问权限不能比父类中被重写方法的访问权限更低(public>protected>default>private)。
重写方法一定不能抛出新的检査异常或者比被重写方法声明更加宽泛的检査型异常。例如,父类的一个方法声明了一个检査异常 IOException,在重写这个方法时就不能抛出 Exception,只能拋出 IOException 的子类异常,可以抛出非检査异常。 - 常见面试题"重写Overriding和重载Overloading是Java多态性的不同表现"
- 重写Overriding是父类与子类之间多态性的一种表现
- 重载Overloading是一个类中多态性的一种表现。
- 如果在子类中定义某个公开的方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。 子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了。
- 如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)
Father类
package javase7.pojo;
public class Father {
private String name;
private int age;
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;
}
public void eat(){//父类的方法
System.out.println(this.name+this.age+"岁,可以吃两碗米饭");
}
public void sport(){
System.out.println("打篮球");
}
//设置父类构造器
public Father(){
System.out.println("我是父类构造器");
}
}
Son类
package javase7.pojo;
/**
* @description 子类已经继承了父类的属性和方法*/
public class Son extends Father{
//我们这里直接使用父类的属性,因此这里不需要再写标识符name 和 age,如果写了,那就完全是子类的东西,和父类一点关系都没有,那么继承就没有意义了
//虽然继承回来的属性是私密的,但可以通过继承回来公开方法去设置我们的name和age属性,这里也不需要写,因为公开的方法我们已经继承并且能使用
//但是子类擅长的运动并不是父类的打篮球,而是踢足球,因此我们需要在这里重写继承回来的sport()方法,通过方法名然后alt+/
@Override
public void sport() {
System.out.println("踢足球");
}
}
测试类
package javase7;
import javase7.pojo.Son;
public class OOP2 {
public static void main(String[] args) {
Son s1 = new Son();//创建的子类对象,
s1.setName("小刘");//他可以使用父类的公开方法设置属性
s1.setAge(18);
s1.eat();//小刘18岁,可以吃两碗米饭,读取设置好的属性
s1.sport();//踢足球,查看子类重写父类的方法,不再是打篮球,而是踢足球
}
}
super关键字(建立在继承的前提下)
- super就是代表父类
- super可以用来调用属性、方法、构造器
- 我们可以在子类的方法或构造器中,通过"super.属性"或"super.方法"的方式,显式的调用 * 父类中声明的属性或方法。但是,通常情况下,我们习惯去省略这个"super.",因为用的少
- 特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的。使用"super.属性"的方式,表明调用的是父类中声明的属性
特殊情况:当子类重写了父类中的方法后,我们想在子类的方法中调用父类中被重写的方法时,必须显式的。使用"super.方法"的方式,表明调用的是父类中被重写的方法 - 我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
- super(形参列表)"的使用,必须声明在子类构造器的首行!
- 我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二选一,不能同时出现。
- 在构造器的首行,既没有显式的声明"this(形参列表)"或"super(形参列表)",则默认的调用的是父类中的空参构造器。super()
- 在类的多个构造器中,至少有一个类的构造器使用了"super(形参列表)",调用父类中的构造器。
改造“方法的重写”里使用的子类
package javase7.pojo;
/**
* @description 子类已经继承了父类的属性和方法*/
public class Son extends Father{
//我们这里直接使用父类的属性,因此这里不需要再写标识符name 和 age,如果写了,那就完全是子类的东西,和父类一点关系都没有,那么继承就没有意义了
//虽然继承回来的属性是私密的,但可以通过继承回来公开方法去设置我们的name和age属性,这里也不需要写,因为公开的方法我们已经继承并且能使用
//但是子类擅长的运动并不是父类的打篮球,而是踢足球,因此我们需要在这里重写继承回来的sport()方法,通过方法名然后alt+/
@Override
public void sport() {
System.out.println("踢足球");
}
//子类构造器中必须至少有一个声明父类的构造器,且调用构造方法只能在构造方法体中,否则就会报错
public Son(){
super();//调用父类定义的无参构造方法,在继承的条件下,没有显式的声明"this(形参列表)"或"super(形参列表)",则默认的调用的是父类中的空参构造器。super(),因此可以不写
// this();每个构造方法只能在第一行写调用别的构造方法.因此只能设置一个调用构造方法,这里也不能写this()原因是递归调用构造函数
System.out.println("我是子类构造器");
}
//新建一个子类独特的方法
public void getSport(){
super.sport();//当方法同名时,使用super.方法强调使用的是父类的方法,而不是子类的方法,java就进原则
this.sport();//this关键字才是调用子类的方法
}
}
改造“方法的重写”里使用的子类的测试类
package javase7;
import javase7.pojo.Son;
public class OOP3 {
public static void main(String[] args) {
Son s1 = new Son();//我是父类构造器,我是子类构造器 创建的子类对象,调用构造器方法
s1.getSport();//打篮球,踢足球 调用子类和父类的sport()方法
}
}
子类对象实例化过程
- 从结果上来讲:
- 子类继承父类以后,就获取了父类中声明的属性或方法。
- 创建子类的对象中,在堆空间中,就会加载所有父类中声明的属性。
- 从过程来讲:
- 当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类构造器和其父类的父类构造器,直到调用了java.lang.Object类中空参的构造器为止。正因为加载过所有的父类结构,所以才可以看到内存中有父类中的结构,子类对象可以考虑进行调用
- 虽然创建了子类对象,调用父类构造器,但自始至终就创建过一个对象,即为new的子类对象。
面向对象特征之三:多态性(继承和方法重写)
- 一个事务多种形态,例如水有液态气态固态
- 重载是一个类中多态的表现。方法同名而形参列表不同
- 重写是子类和父类多态的表现,遵循编译看左边,运行看右边。
- 对象的多态就是父类引用指向子类对象,将子类对象赋值给父类引用
- 编译看左边,运行看右边。意思就是编译时只能用父类的方法,运行时是子类重写父类方法的效果。
- 对象的多态性只适用于方法,不适用于属性(编译和运行都看左边)
package javase7;
public class OOP4 {
public static void main(String[] args) {
Animal animal = new Animal();
animal.eat();//不同的动物吃不同的食物
Animal cat = new Cat();
cat.eat();//猫吃鱼
Animal dog = new Dog();
dog.eat();//狗吃肉
}
}
class Animal{
public void eat(){
System.out.println("不同的动物吃不同的食物");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
类型转换及引用类型转换多态问题问题
package javase7;
import java.util.Date;
public class OOP4 {
public static void main(String[] args) {
Animal animal = new Animal();
animal.eat();//不同的动物吃不同的食物
Animal cat = new Cat();
cat.eat();//猫吃鱼,效果是子类的方法,因为运行看右边
// cat.catMouse();//不能使用子类独有的方法,因为编译看左边
Animal dog1 = new Dog();
dog1.eat();//狗吃肉
// dog.dogName();//也不能使用子类独特的属性,因为编译看左边
Dog dog2=(Dog)dog1;//强转类型后才能使用独特的属性和方法
dog2.dogName="哈士奇";//使用子类独特的属性
/*instanceof关键字使用,用于判断左边的变量是否为右边的类型或右边类型的子类,返回值为boolean类型*/
System.out.println(dog1 instanceof Animal);
/*向下转型常见问题*/
//编译通过,运行不通过
Animal c1 = new Cat();
// Dog d1 = (Dog)c1;//ClassCastException,运行不通过,因为运行右边Cat类型
Animal a1 = new Animal();
// Dog d2 = (Dog)a1;//java.lang.ClassCastException,与上同理
//编译运行都通过
Object d3 = new Dog();
Animal a2 = (Animal)d3;//编译通过,因为Animal是Dog类型的父类
//编译不通过
// Dog c2 = new Cat();//类型用错
// String d1 = new Date();//同上
Object d2 = new Date();
// String str1 = (String)d2;//java.lang.ClassCastException,String类型和Date类型没有子类或者相属关系
}
}
class Animal{
public void eat(){
System.out.println("不同的动物吃不同的食物");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
//子类独特的方法
public void catchMouse(){
System.out.println("猫爪老鼠");
}
}
class Dog extends Animal{
public String dogName;
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
实体类中实例变量不存在变量覆盖
- 若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中
- 对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量,用的还是父类。
package javase7;
public class OOP5 {
public static void main(String[] args) {
Sub s= new Sub();
System.out.println(s.count); //20
s.display();//20
Base b = s;
//==:对于引用数据类型来讲,比较的是两个引用数据类型变量的地址值是否一样。引用类型转换是浅复制
System.out.println(b == s); //true
System.out.println(b.count); //10 特殊!!!!!!!!!!:变量没有被覆,用的还是父类
b.display();//20 继承的方法this.count,运行时看右边,用的是当前类也就是子类的变量
}
}
class Base {
int count= 10;
public void display() {
System.out.println(this.count);
}
}
class Sub extends Base {
int count= 20;
public void display() {
System.out.println(this.count);
}
}
Object 类的使用
- Object类是所有Java类的根父类
- 如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类
- Object类中的功能(属性、方法)就具有通用性
- 属性:无
- equals() / toString() / getClass() / hashCode() / clone() /finalize() 、wait() 、notify()、notifyAll()
- Object类只声明了一个空参的构造器
- 面试题final、finally、finalize的区别?
- final用于声明属性、方法和类,分别表示属性不可变、方法不可覆盖、类不可被继承(不能再派生出新的子类)
- final属性:被final修饰的变量不可变,由于不可变有两重含义,一是引用不可变,二是对象不可变。final属性是引用不可变就是变量指向堆内存的地址不能发生变化,但是对象可以发生变化。
- final方法:当一个方法被声明成final,该方法不允许任何子类重写这个方法,但子类仍然可以使用这个方法
- final类:当一个类被声明为final时, 此类不能被继承,所有方法都不能被重写。但这并不表示final类的成员变量也是不可改变的,要想做到final类的成员变量不可改变,必须给成员变量增加final修饰。值得注意的是,一个类不能既被声明为abstract,又被声明为final。
- finally作为异常处理的一部分,它只能用在try/catch语句中,并且附带着一个语句块,表示这段语句最终一定被执行,经常被用在需要释放资源的情况下。
- finalize是Object类中的一个方法,在垃圾收集器执行的时候会调用被回收对象的finalize()方法,可以覆盖此方法来实现对其他资源的回收,例如关闭文件等。需要注意的是,一旦垃圾回收器准备好释放对象占用的空间,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存
- final用于声明属性、方法和类,分别表示属性不可变、方法不可覆盖、类不可被继承(不能再派生出新的子类)
==操作符与equals方法、重写toString()方法
- ==
- 可以使用在基本数据类型变量和引用数据类型变量中
- 如果果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。(不一定类型要相同)
- 如果比较的是引用数据类型变量:比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体
- == 符号使用时,必须保证符号左右两边的变量类型一致。
- equal()
- 是一个方法,而非运算符
- 在未重写时,其本质就是==
- 只能适用于引用数据类型
- 像String、Date、File、包装类等都重写了Object类中的equals()方法. 不是比较两个引用的地址是否相同,而是比较两个对象的“实体数据类型和内容”是否相同。
- 通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同。那么,我们就需要对Object类中的equals()进行重写,并且重写hashCode()方法
package javase7;
import java.util.Objects;
public class OOP6 {
public static void main(String[] args) {
int i1=10,i2=10;
double d1 = 10.0;
char c1 = 'a';
System.out.println(i1==i2);//true
System.out.println(i1==d1);//true 向大类型转变
System.out.println(c1==97);//true char类型自动转换成int类型97与97比较
//布尔型不能与除布尔类型的任何基本数据类型比较
boolean b1 =true;
// System.out.println(i1==b1);//整数类型不能和布尔类型比较
// System.out.println(d1==b1);//布尔类型不能和布尔类型比较
// System.out.println("hello" == new java.util.Date());//编译不通过.比较引用类型时引用类型要相同
Customer c2 = new Customer("小明", 18);
Customer c3 = new Customer("小明", 18);
System.out.println(c2==c3);//false 比较的是指向堆内存的地址
System.out.println(c2.equals(c3));//true 比较的是类型和所有属性值
System.out.println(c2);//Customer{name='小明', age=18},因为重写了Customer类的toString方法,因此可以以字符串形式输出实体类对象的内容
System.out.println(c3);//Customer{name='小明', age=18},与上同理
String str1 = new String("BAT");
String str2 = new String("BAT");//创建了两个指向不同堆内存的char[]
System.out.println(str1==str2);//false 比较的是两个堆内存地址
System.out.println(str1.hashCode()==str2.hashCode());//true,因为String的hashCode()的生成的值都是由String的值生成的
System.out.println(str1.equals(str2));//true 比较的是两个变量的类型和具体的值
/*这些操作底层都会在堆内存里面创建一个字符串常量池——StringTable,底层是HashTable结构,后面会提到哈希表
* 也就是会存储这些值.当你第一次使用时,他会进行存储.当你第二次或者多次使用这个字符串时,就回去这个池中里面找对应的地址返回给你使用*/
String str3 = "你好啊";
String str4 = "你好啊";
String str5 = "我不好";
System.out.println(str3==str4);//true,两次指向的内存地址是一样的
System.out.println(str4==str5);//false,两个字符串不一样,指向的常量池地址也不一样
}
}
class Customer{
private String name;
private int age;
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;
}
//创造全参构造方法
public Customer(String name, int age) {
this.name = name;
this.age = age;
}
//重写equal()方法
@Override
public boolean equals(Object o) {
if (this == o) return true;//比较是否为同一个对象
if (o == null || getClass() != o.getClass()) return false;//是否为空,或者类型不相同
Customer customer = (Customer) o;//强转类型,因为参数接受进来时变成了Object类型
return age == customer.age &&
Objects.equals(name, customer.name);//比较内容
}
@Override
public int hashCode() {
return Objects.hash(name, age);//通过name和age生成的hash值
}
//重写toString()方法,使得对象可以以字符串的形式输出
@Override
public String toString() {
return "Customer{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
单元测试类使用
- 导入jar包https://download.youkuaiyun.com/download/zjr_java/85764720
- (类)在单元测试类中调用:import org.junit.Test;
- (类)创建一个Java类进行单元测试。此Java类要求是公共的,此类提供一个无参构造器
- (方法)此类单元测试方法要求:权限是public,没有返回值,没有形参。
- (方法)此单元测试方法上需要声明注解:@Test
- 声明好单元测试方法以后,就可以在方法体内测试代码,相当于一个可以在一个类每个测试方法都是一个main方法
import org.junit.Test;
public class OOP7test {
int num = 10;
//第一个单元测试方法
@Test
public void testEquals(){
String s1 = "MM";
String s2 = "MM";
System.out.println(s1==s2);//true
}
//第二个单元测试方法
@Test
public void show(){
int num = 20;
System.out.println(this.num);//10
System.out.println(num);//20
}
}
包装类(Wrapper)的使用
-
java提供了8种基本数据类型对应的包装类,使得基本数据类型的变量具有类的特征
-
byte Byte
-
short Short
-
int Integer
-
long Long
-
float Float
-
double Double
-
boolean Boolean
-
char Character
-
-
注意其中Byte、Short、Integer、Long、Float、Double的父类是:Number
包装类与基本数据类型与String类型的相互转换
import org.junit.Test;
import java.util.Date;
public class OOP8test {
//String类型---> 基本数据类型、包装类,调用包装类的parse包装类型()
@Test
public void test1(){
String s1 = "123";
String s2 = "123a";
//使用数据类型的包装类型的静态方法转换成对应数据类型
int i1 = Integer.parseInt(s1);
// int i2 = Integer.parseInt(s2);//异常
System.out.println(i1);//123
String s3 = "true";
Boolean b1 = Boolean.parseBoolean(s3);
System.out.println(b1); //true
}
//基本数据类型、包装类---》String类型,调用String重载的valueOf(Xxx xxx)
@Test
public void test2(){
int i3 = 6;
//方式一,连接算法,任何数据类型和String类型相加都会变成String类型
System.out.println(6+"");//6
String s4 =""+new Date();
System.out.println(""+new Date());//Fri Jun 24 20:30:43 CST 2022
//方式二,调用String的静态方法valueOf()
String s5 = String.valueOf(12.4);
System.out.println(s5);//12.4
}
//JDK5.0新特性 自动装箱(基本类型-->包装类型)自动拆箱(包装类型-->基本类型)
@Test
public void test3(){
//自动装箱
int i1 = 10;
Integer in1 = i1;//自动装箱
System.out.println(in1);//10
boolean b1 = true;
Boolean bo1 = b1;//自动装箱
System.out.println(bo1);//true
//自动拆箱
int i3 = in1;
System.out.println(i3);//10
boolean b2 = bo1;
System.out.println(b2);//ture
}
//包装类 --》 基本数据类型:调用包装类的xxxValue()
@Test
public void test4() {
Integer in1 = new Integer(12);
int i1 = in1.intValue();
System.out.println(i1 + 1);//13
Float f1 = new Float(12.3f);
float f2 = f1.floatValue();
System.out.println(f2 + 1);//13.3
}
@Test
public void test5() {
int num1 = 10;
// System.out.println(num1.toString());
Integer in1 = new Integer(num1);
System.out.println(in1.toString());
Integer in2 = new Integer("123");
System.out.println(in2.toString());
//报异常
// Integer in3 = new Integer("123abc");
// System.out.println(in3.toString());
Float f1 = new Float(12.3f);
Float f2 = new Float("12.3");
System.out.println(f1);
System.out.println(f2);
Boolean b1 = new Boolean(true);
Boolean b2 = new Boolean("true");
//特殊!!!!!!!!!!!!!!!!!
Boolean b3 = new Boolean("true123");//底层是(s != null) && s.equalsIgnoreCase("true"),如果值不为空且不等于true,那他肯定是false
System.out.println(b3); //false
Order order = new Order();
System.out.println(order.isMale); //false
System.out.println(order.isFemale); //null
}
}
class Order{
boolean isMale;
Boolean isFemale;
}
三木运算的类型转换、Integer自动装箱和new Integer(int i)的区别
import org.junit.Test;
public class OOP9test {
public static void main(String[] args) {
// 如下两个题目输出结果相同吗?各是什么:
/*三目运算符要求表达式要相同类型,因此int提升变成了大类型double,对比完成后重新装箱成Double类型,用Object类型接受,变成了多态*/
Object o1= true? new Integer(1) : new Double(2.0);
/*运行时先是用了Double类型的toString方法,因为编译看左边,运行看右边,因此是变成1.0字符串类型后再打印到控制台*/
System.out.println(o1/*.toString()*/);//1.0
Object o2 = true ? new String("1") : new Double(2.0);
System.out.println(o2);//1
Object o4 = true ? new Boolean(true) : new Double(2.0);
System.out.println(o4);//true
Object o3;
if (true)
o3 = new Integer(1);
else
o3 = new Double(2.0);
System.out.println(o2);//1
}
@Test
public void test() {
Object o1 = true ? new Integer(1) : new Double(2.0);
System.out.println(o1);// 1.0
}
@Test
public void test2() {
Object o2;
if (true)
o2 = new Integer(1);
else
o2 = new Double(2.0);
System.out.println(o2);// 1
}
@Test
public void method1() {
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j); //false
/*只有在自动装箱的时候有效,并且这个范围可以根据需求设置,并不是写死的*/
/* Integer内部定义了一个IntegerCache结构,IntegerCache中定义Integer[]
保存了从-128-127范围的整数。如果我们使用自动装箱的方式,给Integer赋值的范围在其中时,
可以直接使用数组中的元素,不用再去new了。目的,提高效率。*/
Integer m = 1;
Integer n = 1;
System.out.println(m == n);//true
Integer x = 128;//相当于new了一个Integer对象
Integer y = 128;//相当于new了一个Integer对象
System.out.println(x == y);//false
}
}
向量类Vector
- 与后面学的集合Connection中的ArrayList经常用作对比,后面再说
- 解决数组创建长度一旦确定无法再延伸的局限性,有了Vector就可以对存储数据的容器进行动态伸缩.
- Verctor是线程安全的,后面会说
- 创建Verctor对象的语法:<Vector> <变量名> = new Vector();
- 为向量添加元素语法:v.addElement(Object obj); 提示obj必须是对象,但是JDK5.0之后有了自动装箱就不强制必须是对象,基本数据类型也可以自动变成包装类型存入
- 取出向量中的元素语法: Object obj=v.elementAt(0);
- 向量长度v.size();
向量Vector练习
package javase7;
import java.util.Scanner;
import java.util.Vector;
public class OOP10 {
/*需求:
* 利用Vector代替数组处理:从键盘读入学生成绩(以负数代表输入结束),找出最高分,并输出学生成绩等级*/
public static void main(String[] args) {
// 1.实例化Scanner,用于从键盘获取学生成绩
Scanner scan = new Scanner(System.in);
// 2.创建Vector对象:Vector v=new Vector();相当于原来的数组
Vector v = new Vector();
// 3.通过for(;;)或while(true)方式,给Vector中添加数组
int maxScore = 0;
for (;;) {
System.out.println("请输入学生成绩(以负数代表输入结束)");
int score = scan.nextInt();
// 3.2 当输入是负数时,跳出循环
if (score < 0) {
break;
}
//如果输入大于100的值则结束一次循环重新输入
if (score > 100) {
System.out.println("输入的数据非法,请重新输入");
continue;
}
// 3.1 添加操作::v.addElement(Object obj)
// jdk5.0之前:
// Integer inScore = new Integer(score);//先设置包装类
// v.addElement(inScore);//多态
// jdk5.0之后:
v.addElement(score);// 自动装箱,直接可以串
// 4.获取学生成绩的最大值
if (maxScore < score) {
maxScore = score;
}
}
// 5.遍历Vector,得到每个学生的成绩,并与最大成绩比较,得到每个学生的等级。
char level;
for (int i = 0; i < v.size(); i++) {
Object obj = v.elementAt(i);
// jdk 5.0之前:
// Integer inScore = (Integer)obj;
// int score = inScore.intValue();
// jdk 5.0之后:
int score = (int) obj;
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("student-" + i + " score is " + score + ",level is " + level);
}
}
}