-
面向对象
属性:对象的静态特征,成员变量
行为:对象的动态特征,成员方法
-
如何定义类
1.定义成员变量:修饰符 数据类型 变量名 = 初始值;
2.定义成员方法 :修饰符 返回类型 方法名(){};
成员方法不能用static关键字修饰,成员方法没有返回值就不用return同时返回值类型选择void;
-
成员方法详解
1.一个成员方法,可以直接访问当前类中所有的成员变量;
2.一个成员方法,可以直接访问当前类中所有的成员方法;
3.一个类可以调用其他类实例化的对象;
-
JVM内存模型
从内存理解面向对象
-
构造方法
Car c = new Car();
new关键字后面调用的方法就是构造方法,也叫构造器;
构造方法用于创建对象,也可以用于初始化对象中的成员变量;
编译器会给类添加一个默认的构造方法;
语法:修饰符 方法名(参数列表){}
1.构造方法名称和类名相同;
2.构造方法没有返回值;
3.当显式定义构造方法是,编译器将不再生成默认的构造方法;
-
成员方法重载(和静态方法重载类似)
-
构造方法重载
-
this关键字
// this关键字拟解决问题
public class Car{
String brand;
int maxSpeed:
String color;
public Car(String b, String c, int s){
brand = b;
color = c;
maxSpeed = s;
}
}
//this关键字解决
public class Car{
String brand;
int maxSpeed:
String color;
public Car(String brand, String color, int maxSpeed){
this.brand = brand;
this.color = color;
this.maxSpeed = maxSpeed;
}
}
调用这个类的使用者不知道a,b,c分别是什么成员变量;用this关键词可以解决;
在重构方法中,对成员变量加this特别指代当前类的成员变量(属性);
总结:
1.this表示对当前类的引用,同时也区分了成员变量与形参,这时构造函数拿到传过来的参数就赋值给了成员变量;
2.this关键字的用法:(1)**this();**调用当前类构造方法;(2)**this.xxx = xxx;**调用当前对象的成员变量;(3)调用当前类的成员方法;[调用成员变量,成员方法的时候如果不产生冲突可以省略this]
-
面向对象的三大特征
1.封装
四种修饰符(private,protected,public,default[省略])
访问级别:private→default→protected→public
常见方法:
(1).使用private修饰成员变量,避免它被直接访问(只有该对象内部方法可以用私有成员变量,外部无法直接访问该私有成员变量);
(2).为该成员变量增加赋值、取值方法,使用public修饰这两个方法;
(3).在这两个方法中,可以增加任意的数据处理逻辑;
public class Driver {
String name;
private int age;
public Driver(String name, int age){
this.name = name;
this.setAge(age);
}
// 公有的set方法
public void setAge(int age){
if(age > 200){
this.age = 0;
}else{
this.age = age;
}
}
// 公有的get方法
public int getAge(){
return this.age;
}
}// 私有成员变量的调用和构造方法;
- 父类的私有变量,子类可以继承吗?
public class Test {
public static void main(String[] args) {
Father father = new Father();
Child child = new Child();
int fatherAge = father.getAge();
int childAge = child.getAge();
// childAge = child.age;报错,child对于继承的father的私有变量age不可见
System.out.println(fatherAge);
System.out.println(childAge);
father.setAge(80);
fatherAge = father.getAge();
childAge = child.getAge();
System.out.println(fatherAge);
System.out.println(childAge);
child.setAge(30);
fatherAge = father.getAge();
childAge = child.getAge();
System.out.println(fatherAge);
System.out.println(childAge);
}
}
output:100,100,80,100,80,30;
2.继承
(1).直接父类只有一个,间接父类可以有多个;
(2).若一个类没有显式指定父类,则这个类默认继承与java.lang.Object;
(3).父类派生子类,子类扩展了父类;
重写:在子类中,定义与父类同名的方法,用来覆盖父类中的这个方法的逻辑;
@Override
注意!重写和重载之间的区别:重写发生在子类和父类之间;重载也可以发生在父子之间,也可以发生在同一类的多个同名方法之间;
super关键字:子类调用父类的方法;(一般重写的时候都会用的super来保持原来的父类的方法)
!super关键字可以调用父类的成员变量、构造方法、成员方法;
!this是类自己本身的东西,super是自己调用的父类的东西,但是这个东西仍然是属于子类自身的;
!子类构造器之前必调用一次父类构造器,JVM会默认调用无参数的构造器,所以父类必须有无参的构造器;
public class Vehicle{
String brand;
void run(){
System.out.prinln("vehicle run" + brand);
}
}
public class Bus extends Vehicle{
int passengers;
@override
void run(){
System.out.println("Bus run" + super.brand + ‘\t’);
System.out.println(this.passengers);
}
}
// super.brand是属于Bus类自己的,只是调用了父类Vehicle的brand这个数据类型;
3.多态
// 拟解决的问题
public class Driver{
void drive(Bus bus){
...
}
void drive(Car car){
...
}
void drive(Truck truck){
...
}
}
// 多态解决
public class Driver{
void drive(Vehicle vehicle){
vehicle.run();
}
}
//调用时,可以传入vehicle类型的对象,也可以传入vehicle子类的对象;
public class Game{
public static void main(String [] args){
Driver d = new Driver();
Vehicle v =new Vehicle();
Bus b = new Bus();
Truck t = new Truck();
//传入vehicle类型的对象;
d.drive(v);
//传入vehicle子类类型的对象;
d.drive(b);
d.drive(t);
}
}
对象类型的转换
public class Game{
public static void main(String [] args){
// 默认向上转型
Vehicle vehicle = new Bus();
// 强制类型转换
Bus bus = (Bus) vehicle;
}
}
多态只能调用父类的方法,必须instanceof判断实例属于哪个类的对象后,进行强制类型转换,然后调用目标类的方法和成员变量。
**强制类型转换的目的在于:**和多态结合起来使得子类所独特拥有的成员方法或者变量能够得到使用
和上一段代码进行对比:
// 其他代码段不变,对Driver类的drive方法进行修改
public class Driver{
void drive(Vehicle vehicle){
// 在这种情况下只能使用父类的run()方法
vehicle.run();
}
}
public class Driver{
void drive(Vehicle vehicle){
// 用instanceof和强制类型转换实现多态的同时保持子类方法(非重写)能够被使用
// 子类的对象在调用该方法时,类似于发生
// Son son = new son();**Vehicle vehicle = bus;
** Vehicle vehicle = bus;
if( vehicle instanceof Bus){
Bus bus = Bus(vehicle);
System.out.println(bus.passenger);
}else{
vehicle.run();
}
}
}
/* 注意:通过instanceof进行强制类型转换的目的,是为了让子类的对象能够使用子类所独有的方法,
* 不是对父类进行过重写后的方法;
* 如果仅调用子类重写过后的方法,在调用的时候不需要instanceof判断对象属于哪个类,
* 直接调用方法即可
*/
-
强制类型转换的进一步理解:
- 所以在继承中,子类可以自动转型为父类,但是父类强制转换为子类时只有当引用类型真正的身份为子类时才会强制转换成功,否则失败;
Father father = new Father();
Son son = (Son) father;
// 这时会报错的,因为father对象本来就是father类,他是不能进行强制类型转换的;
Father father = new Son();
//子类自动转换成父类,用的是父类的成员方法和变量。如果子类重写方法用得还是子类的方法;
Son son = (Son) father;
// 这个才是正确的强制类型转换;
- 错误的强制类型转换:
public class Test {
public static void main(String[] args) {
Child1 child1 = new Child1();
Father father = child1;
Child2 child2 = (Child2) father;
}
}
/* 报错!com.study.day6.part2.Child1 cannot be cast to com.study.day6.part2.Child2
at com.study.day6.part2.Test.mai */