继承
//继承测试类
/*
* 面向对象的特征之二:继承性
*
* 一、继承性的作用
* 1.减少了代码的冗余,提高了代码的复用性
* 2.便于代码的扩展
* 3.为之后多态性的使用,提供了前提
*
* 二、继承性的格式: class A extends B{}
* A:子类、派生类、subclass
* B:父类、超类、基类、superclass
*
* 关键字extends:延展、扩展
*
* 2.1体现:一旦子类A继承父类B以后,子类A中就获取了父类B中的声明:属性、方法
* 特别的,父类中声明为private的属性或者方法,子类继承父类之后,仍然
* 认为获取了父类私有的结构,只是因为封装性的影响,使得子类不能
* 直接调用父类的结构而已
*
* 2.2 子类继承父类以后,还可以声明自己独有的属性或方法:实现功能的拓展
*
* 三、关于继承性的规定
* 1.java中类的单继承性:一个类可以被多个子类继承,但一个类只能有一个父类(1对多)
* 2.多层继承关系:子父类是相对的概念
* 3.子类继承父类之后,就继承了直接父类以及所有间接父类的属性、方法
*
* 四、1.如果没有显式的声明一个类的父类,则此类继承于java.lang.Object类
* 2.所有的java类(除java.lang.Object类)都直接或间接的继承于java.lang.Object类
* 3.所有java类都具有java.lang.Object类中声明的功能
*
* */
public class PersonTest {
public static void main(String[] args) {
Person p1 = new Person();
p1.age=1;
p1.eat();
Student s1 = new Student();
s1.age=2;
s1.nameString="zoran";
s1.eat();
s1.study();
s1.show();
s1.breath();
Creature c = new Creature();
}
}
public class Person extends Creature{
String nameString;
int age ;
public Person(String nameString, int age) {
this.nameString = nameString;
this.age = age;
}
public Person() {
}
public void eat() {
System.out.println("people can eat");
}
public void sleep() {
System.out.println("people can sleep");
}
}
public class Student extends Person{
// String nameString;
// int age;
String majorString;
public Student(String nameString, int age, String majorString) {
this.nameString = nameString;
this.age = age;
this.majorString = majorString;
}
public Student() {
}
public void show() {
System.out.println(nameString + age);
}
//
// public void eat() {
// System.out.println("people can eat");
// }
// public void sleep() {
// System.out.println("people can sleep");
// }
public void study() {
System.out.println("people can study");
}
}
//示例
/*
* 定义一个ManKind类,包括
* 成员变量int sex 和int salary:
* 方法void manOrWoman():根据sex的值显示“man”(sex==1)或者“woman”(sex==0)
* 方法void employeed():根据salary的值显示“no job”(salary==0)或者“job”(salary!=0)
*
*
*
*
*
*
*
* */
public class ManKind {
private int sex;//性别
private int salary;//薪资
public ManKind() {
}
public ManKind(int sex, int salary) {
this.sex = sex;
this.salary = salary;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public void manOrWoman() {
if(sex==1) {
System.out.println("man");
}else if (sex==0){
System.out.println("woman");
}
}
public void employeed() {
// if(salary==0) {
// System.out.println("no job");
// }else {
// System.out.println("job");
// }
String jobInfoString = (salary==0)?"no job":"job";
System.out.println(jobInfoString);
}
}
/*
* 定义类Kids类继承ManKind,并包括
* 成员变量 int yearsOld;
* 方法printAge()打印yearsOld的值
* */
public class Kids extends ManKind {
private int yearsOld;
public Kids(int yearsOld) {
this.yearsOld = yearsOld;
}
public int getYearsOld() {
return yearsOld;
}
public void setYearsOld(int yearsOld) {
this.yearsOld = yearsOld;
}
public void printAge() {
System.out.println("I AM :"+yearsOld+" YEARSOLD");
}
}
/*
* 定义类KidsTest,在main方法中实例化Kids的对象someKid,用该对象访问其父类
* 的成员变量及方法
*
*
*
*
* */
public class KidsTest {
public static void main(String[] args) {
Kids someKids = new Kids(12);
someKids.printAge();
someKids.setSalary(0);
someKids.setSex(1);
someKids.employeed();
someKids.manOrWoman();
}
}
public class Creature {
public void breath() {
System.out.println("people can breath");
}
}
重写
/*
* 方法的重写(override / overwrite)
* 1.重写:子类继承父类以后,可以对父类中同名同参数的方法进行覆盖操作
*
* 2.重写以后,当创建子类对象以后,通过子类对象调用父类中的同名同参数的
* 的方法时,实际执行时执行的是子类的方法,父类的对象该怎么
* 调用怎么调用
*
* 3.重写的规定:
* 3.1声明:权限修饰符 返回值类型 方法名(形参列表){
* 方法体
* }
* 3.2俗称:子类中的叫 重写的方法,父类中的叫 被重写的方法
* ① 二者的方法名和形参列表必须一致
* ② 重写的方法权限修饰符 大于等于 被重写的方法
* →特殊情况,不能重写父类中权限为private的方法
* ③返回值类型;
* →如果父类方法返回值为void,子类重写的方法必须是void(无返回值)
* →如果父类方法返回值类型是A类型,则子类重写的方法的返回值类型
* 必须是A类或者A类的子类(不能认为 int 是double 的子类哦!)
* →如果父类方法返回值类型是基本数据类型(double),则子类重写的方法的返回值类型
* 必须是相同的基本数据类型(double)
*问:如何区分方法的重载与重写
*
* */
public class PersonTest {
public static void main(String[] args) {
Student student = new Student("计算机科学与技术");
student.eat();
student.walk(10);
student.study();
System.out.println(student.info());
}
}
public class Perosn {
String nameString ;
int age;
public Perosn() {
}
public Perosn(String nameString, int age) {
super();
this.nameString = nameString;
this.age = age;
}
public void eat() {
System.out.println("eat food");
}
public void walk(int distance) {
System.out.println("walk"+distance+"km");
}
public Object show() {
return null;
}
public double info () {
return 1.0;
}
}
public class Student extends Perosn {
String majorString;
public Student() {
}
public Student(String majorString) {
super();
this.majorString = majorString;
}
public void study() {
System.out.println("student can study"+majorString);
}
//对父类的方法重写
public void eat() {
System.out.println("student eat better");
}
public void walk(int distance) {
System.out.println("student walk better "+distance );
}
public String show() {//String 是 Object 的子类
return null;
}
public double info () {
return 2.0;
}
}
super关键字
/*super关键字的使用
* 1.super理解为:父类的....
* 2.super可以用来调用:属性 方法 构造器
* 3.super的使用:调用属性和方法
* 3.1可以在子类的方法或者构造器中使用super.属性 或者 super.方法 的方式
* 显式的调用父类中声明的属性或者方法,通常情况下习惯省略super.
* →当子类和父类定义了同名的属性,必须用super.在子类中调用父类的属性
* →如果重写了父类的方法,也要用super.来调用父类的方法
* 4.super调用构造器
* 4.1可以在子类的构造器中显式的使用super(形参列表)的方式表示调用父类中声明的指定的构造器
* 4.2super(形参列表)在使用时,必须声明在构造器的首行,然后this(形参列表)也只能放首行,所以
* 4.3在类的构造器中,super(形参列表)和this(形参列表)只能二选一
* 4.4在构造器的首行,没有this也没有super,默认调用父类空参构造器
* */
public class SuperTest {
public static void main(String[] args) {
Student1 student1 = new Student1();
student1.show();
Student1 student2 = new Student1("TOM",12,"IT");
student2.show();
}
}
public class Person1 {
String nameString;
int age;
int id=1002;
public Person1(String nameString, int age) {
super();
this.nameString = nameString;
this.age = age;
}
public Person1() {
super();
}
public Person1(String nameString) {
this.nameString=nameString;
}
public void eat() {
System.out.println("people can eat");
}
public void walk() {
System.out.println("people can walk");
}
}
public class Student1 extends Person1 {
String majorString;
int id=1002;//学号
public Student1() {
}
public Student1(String majorString) {
this.majorString=majorString;
}
public Student1(String nameString,int age,String maString) {
super(nameString,age);//调用父类中 形参为nameString 和 age的构造器
this.majorString=maString;
}
@Override
public void eat() {
System.out.println("student can eat better");
}
public void study() {
System.out.println("student can study");
}
public void show() {
System.out.println("name = "+this.nameString + "age = "+super.age);
System.out.println("id = "+id);//1001
System.out.println("id = "+super.id);//1002
}
}
多态性
/*多态性
*
* 1.理解多态性:可以理解为一个事物的多种形态
* 2.何为多态性:
* 对象的多态性:父类的引用指向子类的对象
* (或者叫 子类的对象赋给父类的引用)
*
* 3.多态的使用:虚拟方法调用
* 有了对象的多态性之后,在编译期,只能调用父类中声明的方法
* 但在运行期,实际执行的是子类重写的方法
* 总结:编译看左边,执行看右边
* Perosn p2 =new Man();
* p2.eat();//man can eat more to earn money
* 编译的时候是Person的方法,执行的时候是Man的方法,Ctrl点eat()进入Perosn类
*
* 4.多态性的使用前提
* ①必须有类的继承关系(才能有重写等等操作)没有继承就没有多态性
* ②方法的重写(否则就没必要new子类对象)
*
* 5.对象的多态性,只适用于方法,不适用于属性(编译运行都看左边)
*
* 虚拟方法调用再理解
* 正常的方法调用
* Person e = new Person();
* e.getInfo();
* Student e = new Student();
* e.getInfo();
* 虚拟方法调用
* 子类中定义了与父类同名的方法(重写),在多态情况下,将此时父类的方法称为虚拟方法
* 父类根据赋给它的不同子类对象,动态调用该子类的该方法
* Person e = new Student();
* e.getInfo();// 调用Student类的getInfo方法
* 编译时e为Person类型,而方法的调用是运行时确定的,所以调用的是Student类的方法--动态绑定
*
* */
public class PersonTest {
public static void main(String[] args) {
Perosn p1 = new Perosn();
p1.eat();
p1.walk();
Man m1 = new Man();
m1.age =25;
m1.eat();
m1.walk();
m1.earnMoney();
Woman w1 = new Woman();
w1.eat();
w1.walk();
w1.goShopping();
//*****************************
//多态性:父类的引用指向子类的对象
System.out.println("**********************");
Perosn p2 =new Man();
//当调用子父类同名同参数的方法时,调用的是子类重写后的方法
p2.eat();//man can eat more to earn money
p2.walk();//man can walk very good
//p2.earnMoney();报错,只能调用父类声明过的方法,不能调用自己独有的方法
System.out.println(p2.id);//1001
}
}
public class Perosn {
String nameString;
int age;
int id=1001;
public void eat() {
System.out.println("people can eat");
}
public void walk() {
System.out.println("people can walk");
}
}
public class Man extends Perosn {
boolean isSmoking;
int id = 1002;
public void earnMoney() {
System.out.println("man can earn Money");
}
//重写父类方法
public void eat() {
System.out.println("man can eat more to earn money");
}
public void walk() {
System.out.println("man can walk very good");
}
}
public class Woman extends Perosn{
boolean isBeauty;
public void goShopping() {
System.out.println("woman can go shopping");
}
//重写父类方法
public void eat() {
System.out.println("woman can eat litter");
}
public void walk() {
System.out.println("woman can walk to shop");
}
}
//举例
//多态性使用举例一:
public class AinamlTest {
public static void main(String[] args) {
AinamlTest test = new AinamlTest();
test.func(new Dog());
//dog can eat shit
//dog can shout WAWAWA
test.func(new Cat());
//cat can eat fish
// cat can shout MIMIMI
}
public void func(Animal animal) {
animal.eat();
animal.shout();
}
// public void func(Dog dog) {
// dog.eat();
// dog.shout();
// } 没有多态性需要写很多重载的方法
// public void func(Cat cat) {
// cat.eat();
// cat.shout();
// }
}
class Animal{
public void eat() {
System.out.println("animal can eat");
}
public void shout() {
System.out.println("animal can shout");
}
}
class Dog extends Animal{
public void eat() {
System.out.println("dog can eat shit");
}
public void shout() {
System.out.println("dog can shout WAWAWA");
}
}
class Cat extends Animal{
public void eat() {
System.out.println("cat can eat fish");
}
public void shout() {
System.out.println("cat can shout MIMIMI");
}
}
//举例二
class Order{
public void method(Object obj) {
}
}
instanceof关键字的使用
/*多态性
*
* 1.理解多态性:可以理解为一个事物的多种形态
* 2.何为多态性:
* 对象的多态性:父类的引用指向子类的对象
* (或者叫 子类的对象赋给父类的引用)
*
* 3.多态的使用:虚拟方法调用
* 有了对象的多态性之后,在编译期,只能调用父类中声明的方法
* 但在运行期,实际执行的是子类重写的方法
* 总结:编译看左边,执行看右边
* Perosn p2 =new Man();
* p2.eat();//man can eat more to earn money
* 编译的时候是Person的方法,执行的时候是Man的方法,Ctrl点eat()进入Perosn类
*
* 4.多态性的使用前提
* ①必须有类的继承关系(才能有重写等等操作)没有继承就没有多态性
* ②方法的重写(否则就没必要new子类对象)
*
* 5.对象的多态性,只适用于方法,不适用于属性(编译运行都看左边)
*
* 虚拟方法调用再理解
* 正常的方法调用
* Person e = new Person();
* e.getInfo();
* Student e = new Student();
* e.getInfo();
* 虚拟方法调用
* 子类中定义了与父类同名的方法(重写),在多态情况下,将此时父类的方法称为虚拟方法
* 父类根据赋给它的不同子类对象,动态调用该子类的该方法
* Person e = new Student();
* e.getInfo();// 调用Student类的getInfo方法
* 编译时e为Person类型,而方法的调用是运行时确定的,所以调用的是Student类的方法--动态绑定
* ******************************************************************
*
* */
public class PersonTest {
public static void main(String[] args) {
Perosn p1 = new Perosn();
p1.eat();
p1.walk();
Man m1 = new Man();
m1.age =25;
m1.eat();
m1.walk();
m1.earnMoney();
Woman w1 = new Woman();
w1.eat();
w1.walk();
w1.goShopping();
//*****************************
//多态性:父类的引用指向子类的对象
System.out.println("**********************");
Perosn p2 =new Man();
//当调用子父类同名同参数的方法时,调用的是子类重写后的方法
p2.eat();//man can eat more to earn money
p2.walk();//man can walk very good
//p2.earnMoney();报错,只能调用父类声明过的方法,不能调用自己独有的方法
System.out.println(p2.id);//1001
System.out.println("***********************************************");
//不能调用子类特有的方法,因为p2是一个Perosn类型
//p2.earnMoney();
//p2.isSmoking=true;
p2.nameString="TOM";
//有了对象的多态性以后,内存中实际上是加载了子类的特有的属性和方法的
//但是由于声明为父类类型,导致编译时只能调用父类中的属性和方法
//如何调用子类独有的属性和方法?
Man m2= (Man)p2;//向下转型--强制类型转换,强制转换成Man类型的
m2.earnMoney();
m2.isSmoking=true;
//使用强转时,可能出现ClassCastException的异常
//w2.goShopping();类型转换异常
//instanceof关键字的使用
/*
* a instanceof A:判断对象a是否是类A的实例,如果是返回true,不是返回false
*
* 使用情景:为了避免向下转型的时候出现ClassCastException的异常,先进行instanceof,
* 判断对象a是否是类A的示例,如果是返回true,不是返回false
*
*
* 如果 a instanceof A 返回true,则 a instanceof B也返回true
* 则 类B是类A的父类
* */
if(p2 instanceof Woman) {
Woman w2 =(Woman)p2;
w2.goShopping();
System.out.println("woman");
}
if(p2 instanceof Man) {
Man w3 =(Man)p2;
w3.earnMoney();
System.out.println("man");
}
}
}
Object类
/*
* Object类
* 1.是所有类的根父类
* 2.如果类在声明的时候没有extends关键字,默认继承java.lang.Object类
*
* 两个常用方法
* 1.equals()
* 2.toString()
*
*
* 面试题: == 和 equals()的区别
* ==:运算符,可以用来比较基本数据类型变量和引用数据类型变量
* equals():
* 1.是方法,不是运算符
* 2.只能适用于引用数据类型:比较两个对象的地址值是否相同
* 3.像String Date File 包装类都重写了Object类中的equals方法
*
* toString的使用
* 1.输出一个对象的引用时,调用的是当前对象的toString()
* 2.String Data file 包装类都重写了此方法,使得在调用对象的此方法时,返回“实体内容”信息
*
*
* */
import java.sql.Date;
public class ObjectTest {
public static void main(String[] args) {
Customer cust1 = new Customer();
System.out.println(cust1.toString());//com.zoran.java4.Customer@3830f1c0
System.out.println(cust1);//com.zoran.java4.Customer@3830f1c0
String string = "MM";
System.out.println(string);
Date date = new Date(464654564654L);//MM
System.out.println(date.toString());//1984-09-22
}
}
class Customer
{
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
包装类
import org.junit.Test;
/*包装类的使用
*
* 1.Java提供了八种基本数据类型对应的包装类,使得基本数据类型的变量具有类的特征
* 基本数据类型 包装类
* byte Byte
* short Short
* int Integer
* long Long
* float Float
* double Double
* boolean Boolean
* char Character
* 2.掌握:基本数据类型,包装类,String三者之间的转换
*
*
* */
public class WrapperTest {
// 基本数据类型==>包装类:调用包装类的构造器
@Test
public void test1() {
int number1 = 10;
// System.out.println(number1.toString); 错误
Integer in1 = new Integer(number1);
System.out.println(in1.toString());// 10
Integer in2 = new Integer("123");
System.out.println(in2.toString());// 123
Float f1 = new Float(12.3f);
Float f2 = new Float("12.3");
System.out.println(f1);// 12.3
System.out.println(f2);// 12.3
Boolean boolean1 = new Boolean(true);// true
Boolean boolean2 = new Boolean("true");// true
Boolean boolean3 = new Boolean("true123");// fasle 忽略大小写,长得和true即可输出true
System.out.println(boolean1);
System.out.println(boolean2);
System.out.println(boolean3);
Order o1 = new Order();
System.out.println(o1.isMale);// 默认值false
System.out.println(o1.isFemaleBoolean);// null isFemaleBoolean 是 Boolean的对象,默认值是null
// 数据转换异常
// Integer in3 = new Integer("123abc");
// System.out.println(in3.toString());//123
}
class Order{
boolean isMale;
Boolean isFemaleBoolean;
}
// 包装类转化为基本数据类型:调用包装类XXX的XXXValue()
@Test
public void test2() {
Integer in1 = new Integer(12);
int i1 = in1.intValue();
System.out.println(i1);// 12
Float float1 = new Float(12.3);
float f1 = float1.floatValue();
System.out.println(f1);// 12.3
}
//在JDK5.0加入新特性,自动装箱与自动拆箱
@Test
public void test3() {
int num1 = 10;
//需要基本数据类型转化成包装类的对象
Integer in1 = new Integer(num1);
method(in1);
//自动装箱(不用new构造器)
int num2 =10;
Integer in2 = num2;
boolean b1 = true;
Boolean b2 = b1;
//自动拆箱
int num3 = in2;
}
public void method(Object obj) {
System.out.println(obj);
}
//基本数据类型/包装类==>String:调用String重载的valueOf方法
@Test
public void test4() {
int num1 =10;
// String string1 =num1; 错误的写法
//方式1:连接运算
String str1 = num1+" abc";
//方式2:调用String重载的valueOf方法
float f1 = 12.3f;
String str2 = String.valueOf(f1);
System.out.println(str2);//"12.3"
Double double1= new Double(12.4);
String str3 = String.valueOf(double1);
System.out.println(str3);//"12.4"
}
//String =>> 基本数据类型/包装类:调用包装类的parseXXX()
@Test
public void test5() {
String str1 = "123";
// int num1 = (int)str1;错误
// Integer in1 = (Integer) str1;错误
int num1 = Integer.parseInt(str1);
System.out.println(num1);//123
System.out.println(num1+1);//124
String string2 = "true";
boolean b1 = Boolean.parseBoolean(string2);
System.out.println(b1);//true
}
}
总结:
基本数据类型与包装类之间的转换:自动装箱与自动拆箱
基本数据类型/包装类>>>Stirng:调用String类的valueOf()方法
String>>>基本数据类型/包装类:调用包装类的XXX.parsexxx()方法