关于 Java面向对象(2)

面向对象

  • java中,万事万物都是对象
class ClassName{
//body;
}

ClassName cn = new ClassName();

尽管一切都看作是对象,但是你操纵的却是一个对象的引用(reference)。在这里有一个很形象的比喻:你可以把车钥匙和车看作是一组对象引用和对象的组合。

当你想要开车的时候,你首先需要拿出车钥匙点击开锁的选项,停车时,你需要点击加锁来锁车。车钥匙相当于就是引用,车就是对象,由车钥匙来驱动车的加锁和开锁。并且,即使没有车的存在,车钥匙也是一个独立存在的实体,也就是说,你有一个对象引用,但你不一定需要一个对象与之关联,也就是

Car carkey;

这里创建的只是引用,而并非对象,但是如果你想要使用这个引用时,会返回一个异常,告诉你需要一个对象来和这个引用进行关联。一种安全的做法是,在创建对象引用时同时把一个对象赋给它。

Car carkey=new Car();

在Java中,一旦创建了一个引用,就希望它能与一个新的对象进行关联,通常使用new操作符来实
现这一目的。new的意思是,给我一个新对象,如果你不想相亲,自己new一个对象就好了。

祝你下辈子幸福。

  • 属性与方法

  • 构造方法

    • 只在创建对象时使用
    • 可以有多个
class Apple {
int sum;
String color;
public Apple(){}
public Apple(int sum){}
public Apple(String color){}
public Apple(int sum,String color){}
}

各个Apple的参数不一样,是一种多态的表现

class Apple {
int sum;
String color;
public Apple(){}
public Apple(int sum){}
public Apple(String color){}
public Apple(int sum,String color){}
}

如果没有定义构造方法,JVM会自动生成一个无参数的构造方法

重载

看人下菜碟:看人,根据不同的人;下菜,是把做好的菜端来放在桌子上;一般都是用此话的引申义,比喻不能一视同仁、待人因人而异,根据不同的人给予不同的待遇。

也就是同一个函数名的函数根据传入变量的不同选择执行哪一个

方法重写

描述父类和子类,子类重写了父类的方法

class Fruit {
public void eat(){
System.out.printl('eat fruit');
}

class Apple extends Fruit{
@Override
public void eat(){
System.out.printl('eat apple');
}
}
  • 重写的原则
    • 重写的方法必须要和父类保持一致,包括返回值类型,方法名,参数列表也都一样
    • 重写的方法可以使用 @Override 注解来标识
    • 子类中重写方法的访问权限不能低于父类中方法的访问权限

对象销毁

Java基于C++,和C++一样不需要手动管理对象的销毁

在著名的一书《深入理解Java虚拟机》中提到一个观点:
Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的人却想出来。

this和super

  • this和super都是Java中的关键字

  • this表示的当前对象,this可以调用方法、调用属性和指向对象本身this在Java中的使用一般有三种:指向当前对象

public class Apple {

int i = 0;

Apple eatApple(){
i++;
return this;
}

public static void main(String[] args){
Apple apple = new Apple();
apple.eatApple().eatApple();
}
}

这段代码比较特别,eatApple()方法竟然可以调用多次

你在后面还可以继续调用,为什么?

是this在发挥作用:在eatApple方法中加了一个return this 的返回值,也就是说哪个对象调用 eatApple 方法都能返回对象的自身

✨this最常用的方法是修饰属性:

public class Apple {
private int num;

public Apple(int number){
this.number = num;
}

public static void main(String[] args){
new Apple(10);
}
}

✨this还可以结合构造函数使用充当全局关键字

public class Apple {
private int num;
private String color;

public Apple(int num){
this(num,"红色");
}
public Apple(String color){
this(1,color);
}
public Apple(int num, String color){
this.num=num;
this.color=color;
}
}

你会发现上面这段代码使用的不是this,而是this(参数)。它相当于调用了其他构造方法,然后传递参数进去

⚠️这里注意一点:this()必须放在构造方法的第一行,否则编译不通过

  • 如果你把this理解为指向自身的一个引用,那么super就是指向父类的一个引用
  • super关键字和this一样,你可以使用super.对象来引用父类的成员
public class Fruit {
int num;
String color;

public void eat(){
System.out.println("eat Fruit");

}

public class Apple extends Fruit{

@Override
public void eat(){
super.num=10;
System.out.println("eat"+num+"Apple");
}
}

封装

table2

继承

  • 继承的关键字是extends

    class Son extends Father{

    }
  • 如果 Son 没有实现自己的方法的话,那么默认就是用的是父类的 feature 方法。如果子类实现了自己的 feature 方法,那么就相当于是重写了父类的 feature 方法,这也是我们上面提到的重写

多态

步骤:

  • 继承
  • 重写父类方法
  • 父类引用指向子类对象

继承、重写

public class Fruit {
int num;
public void eat(){
System.out.println("eat Fruit");

}

public class Apple extends Fruit{
@Override
public void eat(){
super.num=10;
System . out . println ( " eat " + num + " Apple " ) ;
}
}

父类引用指向子类对象

public static void main(String[] args){
Fruit fruit = new Apple();
fruit.eat()
}

可以发现 main 方法中有一个很神奇的地方,Fruit fruit = new Apple(),Fruit类型的对象竟然指向了Apple对象的引用,这其实就是多态->父类引用指向子类对象,因为Apple继承于Fruit,并且重写了eat方法,所以能够表现出来多种状态的形式。

组合

组合其实不难理解,就是将对象引用置于新类中即可。组合也是一种提高类的复用性的一种方式。如果
想让类具有更多的扩展功能,只需要记住一句话

多用组合,少用继承

public class SoccerPlayer {
private String name;
private Soccer soccer;
}
public class Soccer {
private String soccerName;
}

组合与继承的区别

组合与继承的区别

代理

  • 代理的大致描述是,A想要调用B类的方法:
    1. A不直接调用
    2. A会在自己的类中创建一个B对象的代理
    3. 再由代理调用B的方法

例如如下代码:

public class Destination {
public void todo(){
System.out.println("control...");
}

public class Device {
private String name;
private Destination destination;
private DeviceController deviceController;
public void control(Destination destination){
destination.todo();
}
}

public class DeviceController {
private Device name;
private Destination destination;
public void control(Destination destination){
destination.todo();
}
}

static

用在没有创建对象时调用方法/变量

static String name = "hellworld"

使用static修饰的方法称为静态方法,静态方法能够直接使用类名.方法名进行调用。由于静态方法不依赖于任何对象就可以直接访问,因此对于静态方法来说,是没有this关键字的,实例变量都会有this关键字。在静态方法中不能访问类的非静态成员变量和非静态方法。

static void printMessage(){
System.out.println("Hello World!")
}

static除了修饰属性和方法外,还有静态代码块的功能,可用于类的初始化操作。由于静态代码块随着类的加载而执行,因此,很多时候会将只需要进行一次的初始化操作放在static代码块中进行。

public class StaicBlock {
static{
System.out.println("I'm A static code block");
}

final

  • final的意思是最后的、最终的,它可以修饰类、属性和方法。
    • final修饰类(class)时,表明这个类不能被继承。final类中的成员变量可以根据需要设为final,但是要注意final类中的所有成员方法都会被隐式地指定为final方法。
    • final修饰方法时(method),表明这个方法不能被任何子类重写。因此,如果只有在想明确禁止该方法在子类中被覆盖的情况下才将方法设置为 final。
    • final修饰变量分为两种情况,一种是修饰基本数据类型,表示数据类型的值不能被修改;一种是修饰引用类型,表示对其初始化之后便不能再让其指向另一个对象。

内部类

内部类是一种非常有用的特性,定义在类内部的类,持有外部类的引用,但却对其他外部类不可见,看
起来就像是一种隐藏代码的机制.

创建内部类

直接将一个类定义在外围类的里面

public class OuterClass {
private String name ;
private int age;

class InnerClass{
public InnerClass(){
name ="hello";
age=25;
}
}
}