Java面向对象

一.类和对象

1.属性

直接把field用public暴露给外部可能会破坏封装性,所以用private
外部代码可以调用get()方法和set()方法来间接获取和修改指定的私有成员变量的值

2.方法

定义语法

修饰符 方法返回类型 方法名(方法参数列表) {
    若干方法语句;
    return 方法返回值;
}

若方法中没有returun返回值,则该方法的返回类型为void类型

参数
方法的参数传递机制

形参:声明方法时定义的参数,形参前必须有数据类型 格式:方法名(数据类型 形参)
实参:调用方法时给方法传递的实际数据,使用格式:对象名.方法名(实参)

可变参数:

定义格式
方法名(参数列表,数据类型 … 变量)
注意:
可变参数只能处于参数列表的最后
一个方法最多只能包含一个可变参数
可变参数本质是一个数组,因此在调用时,既可以传入多个参数,也可传入一个数组

构造方法

作用:在创建对象时初始化对象中的属性值
构造方法的名称必须是类名。构造方法没有返回类型(也没有void),调用构造方法,必须用new操作符。
不能被static、final、synchronized、abstract和native修饰。构造方法不能被子类继承,所以用final和abstract修饰没有意义。

构造方法用于初始化一个新建的对象,所以用static修饰没有意义
语法:
访问符 类名 (参数){
}

this关键字:

this代表当前对象的内存地址,
在实例方法或者构造方法中,为了区分局部变量和实例变量,this不能省略
代表当前类将来产生的对象,即将来用该类new出来的对象,用于获取当前类的对象的引用

方法的调用

1.调用非静态方法
对象名.方法名()
2.调用静态方法
类名.方法名()

Person p1 = new Person("Xiao Ming", 15); // 既可以调用带参数的构造方法
Person p2 = new Person(); // 也可以调用无参数构造方法
方法重载

方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。
目的:功能类似的方法使用同一名字,更容易记住,因此,调用起来更简单。

方法重写

子类重写了父类的方法
注意:方法名相同,方法参数相同,但方法返回值不同,也是不同的方法

对象

创建对象

语法:类名 变量名=new 类名();
创建类的对象分为两步
1.定义该类的一个变量,此时在栈上会分配空间储存对象在堆中的地址(即对象的引用)
2.创建该对象的实际物理空间,即在堆中为该对象分配空间,并把此空间的地址(即引用)赋给对象名,此步骤通过new关键字来实例化该类的一个对象

使用对象

创建对象后就可以使用对象
访问对象的属性 语法:对象名.属性名
调用对象的方法 语法:对象名.方法名()

二.面向对象三大特征

封装

实际上就是信息隐藏,将类中的成员属性和成员方法修饰为私有化,数据被保护在对象的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系,即get/set方法。

其他对象只能通过该对象提供的get/set方法,与这个封装的对象进行交流和交互。也就是说用户是无需知道对象内部的细节(当然也无从知道),但可以通过该对象对外提供的接口来访问该对象。

  • 访问符:用于指明类、属性或方法的访问权限
    public公共访问权限,可被同一包或不同包的所有类访问
    protected子类访问权限,可以被同一包的其它类访问,也可以被其他包的子类访问
    friendly包访问权限,如果没设置访问符则默认friendly包访问权限,可被同一包中所有类访问
    private 当前类访问权限,只能被当前类的其它成员访问
  • 修饰符:用于指明类的特性
    abstarct(抽象)
    static(静态)
    final(最终)

如果有很多代码都使用了Dog这个类;当某一天这个类的age属性需要换成String类型,那么,外部使用它的任何地方都需要需改xxx.age=“xxx”,这将是非常繁琐的一个过程,那该怎么办呢?很简单,使用private修饰符将属性封装,开放访问接口的方法,我们只需要修改一下set方法就能完美解决。

public static void main(String[] args) {
	Dog d1 = new Dog();
	//调用时发生变化
	d1.setName("旺财");
	d1.setAge(3);
	}
}
class Dog{
	private String age;//修改为String类型
	private String name;
	//将属性私有化,提供set方法,将int类型的值转成String
	public void setAge(int age) {
		this.age = String.valueOf(age);
	}
	public void setName(String name) {
		this.name = name;
	}

这样外部使用它的地方都不用修改,我们只用简单的修改对象内部就可以了,更加方便快捷。到了这里我们应该可以看出,封装确实可以使我们容易地修改类的内部实现,而无需修改使用了该类的客户代码。

这里还可以体现出一些封装属性的优势,案例如下:

public static void main(String[] args) {
	Dog d1 = new Dog();
	d1.setName("旺财");
	d1.setAge(300);//狗的年龄赋值很明显不合理,这里就需要在set方法中给出提示
	}
}
class Dog{
	private String age;
	private String name;
	public void setAge(int age) {
		if(age>100||age<0) {
			System.out.println("你见过超过100岁的狗狗吗?");
		}else  {
			this.age = String.valueOf(age);
		}
		
	}
	public void setName(String name) {
		this.name = name;
	}
		
}

继承

作用:通过继承,子类可以使用父类中的非私有属性和非私有方法,从而提高代码的重用性,提高开发效率。
子类自动获得了父类的所有字段,严禁定义与父类重名的字段!
为了让子类可以访问父类的字段,把private改为protected。用protected修饰的字段可以被子类访问
除了父类中私有的属性和方法,子类必须全部继承。
3、子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
4、子类可以用自己的方式实现父类的方法(即方法的重写/覆盖)。
5、构造器而言,它只能够被调用,而不能被继承,子类可以使用super()调用父类构造器。
6、对于继承而已,子类会默认调用父类的无参构造,但是如果父类没有无参构造,子类必须要在其构造方法中的第一行代码调用指定父类的构造器,传递对应参数。
7、Java 的继承是单继承,即每个子类只能拥有一个直接父类,但是该父类可以有多个子类
通过extends关键字实现继承
语法格式
访问符 修饰符 class 子类 extends 父类{ }

class Father{
	//父类中的非私有属性都会被继承
	public int age;
	private double money;
	String home;
	//父类中的非私有方法都会被继承
	void eat() {} //吃东西
	public void sleep() {}//睡觉
	private void soner() {}//打呼噜
	//父类构造方法如果有参数,子类必须在构造方法第一行中调用
	public Father(int x) {
		//父类如果写了有参构造,那么默认的无参构造将不再生效
	}
}
class Son extends Father{
 
	public Son(int x) {
		super(x);//调用父类构造 super() 
		age=12;//继承后拥有父类的属性
		home="王者峡谷河道下边的草丛";
		//money=3.0; 父类私有属性无法访问
		sleep();//可以执行父类中的非私有方法
	}
	
}

子类继承父类,默认在子类构造方法中调用父类构造,在创建子类实例对象时,实际上的执行顺序是(父类构造——子类构造)。在类的构造器中还有一段特别的代码,优先与构造器,在创建对象时优先执行,话不多说直接看代码:

public static void main(String[] args) {
		Z z1 = new Z();//创建子类实例对象时,实际上的执行顺序
	}
	
}
class F {
	static { 
		//静态代码块,只有方法的大括号,没有方法名返回值等任何内容
		System.out.println("父类静态代码块");
	}
	{
		//构造代码块,只有方法的大括号,没有方法名返回值等任何内容
		System.out.println("父类构造代码块");
	}
	public F() {
		// 父类构造器
		System.out.println("父类构造器");
	}
}
class Z extends F{
	static { 
		//静态代码块,只有方法的大括号,没有方法名返回值等任何内容
		System.out.println("子类静态代码块");
	}
	{
		//构造代码块,只有方法的大括号,没有方法名返回值等任何内容
		System.out.println("子类构造代码块");
	}
	public Z() {
		// 父类构造器
		System.out.println("子类构造器");
	}
}

运行结果

父类静态代码块
子类静态代码块
父类构造代码块
父类构造器
子类构造代码块
子类构造器

多态

面向对象三大特征,封装、继承、多态。从某种意义上来讲,封装和继承几乎就是为了多态而准备的,也是三大特征中最重要的知识点。

多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。简单来说就是不同类型的对象(父类或子类)调用同一个方法,根据发出调用的对象不同,执行的方法也就不同。

实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。

多态的作用:消除类型之间的耦合关系。

这里举一个简单的小例子:父类是个农民,技能是使用锄头耕地。子类继承了父类,重写了父类的锄头耕地技能,更新换代为使用拖拉机耕地。如果是父类对象调用这个技能,就是使用锄头手动耕地,如果是子类对象调用这个技能,就是使用拖拉机耕地。

java实现多态有三个必要条件:继承、重写、父类引用指向子类对象。
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
父类引用指向子类对象(向上转型):在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。

public class People {//人类 作为所有职业的父类
	
	public int age;
	public String name;
	void work() {//父类的方法
		System.out.println("劳动");
	}
	public static void main(String[] args) {
		//父类引用指向子类对象就是多态性的体现
		People p1 = new Doctor();// p1的类型是人类类型,但是指向的实例对象是医生
		p1.work();//父类引用发出的调用,调用到的是医生类中重写父类的方法
		People p2 = new Teacher();
		p2.work();//父类引用发出的调用,调用到的是教师类中重写父类的方法
	}
	
}
 
class Doctor extends People{
	@Override
	void work() {//医生类继承人类,重写工作方法
		System.out.println("救死扶伤");
	}
	
}
class Teacher extends People{
	@Override
	void work() {//教师类继承人类,重写工作方法
		System.out.println("教书育人");
	}
}

运行结果

救死扶伤
教书育人

注意:指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的。比如说方法的重载,尽管方法名称相同,但是父类只能调用到子类重写的方法,调用不到重载方法。

class Teacher extends People{
   @Override
   void work() {//教师类继承人类,重写work方法
   	System.out.println("教书育人");
   }
   void work(String name) {//重载了work方法,但是此方法父类引用无法调用
   	System.out.println("负责教导的课程是"+name);
   }
}

多态的好处:

1.可替换性(substitutability)。多态对已存在代码具有可替换性。例如:医生、律师、程序员都是人类的子类,根据使用场景不同随时可以替换为符合的职业。
2.可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在拥有了医生、律师的继承上,还可以继续添加新的职业,比如主播,运动员等,都是添加为人类的多态性。
3.接口性(interface-ability)。多态是超类通过抽象方法,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。每个子类都可以根据自身的特性去重写父类的抽象方法。
4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

三.类之间的关系

继承

依赖关系

在一个类的方法中操作另一个类的对象,则称其依赖于第二个类
例如方法的参数时某个类的对象

关联关系

体现为一个类中使用另一个类的对象作为该类的成员变量

聚合关系

聚合关系是关联关系的一种特例,体现是整体与部分的关系,
表现为一个类(整体)由多个其他类的对象(部分)作为该类的成员变量

组成关系

四.抽象类

定义抽象类

语法格式:

访问符 abstract class 类名{
	访问符 abstract 返回类型 方法名(参数列表)
}

有抽象方法的类只能被定义为抽象类,但抽象类中可以没有抽象方法
抽象类不能被实例化,即无法用new创建一个抽象类的对象
抽象类作为子类的模版,避免子类设计的随意性
对象不能由抽象类直接创建,只可以通过抽象类派生出新的子类,再由其子类来创建对象
abstract 关键字不能用来修饰属性和构造方法
抽象方法必须被子类重写才有意义,因此不能用private修饰抽象方法
抽象方法,没有方法体

public abstract void call(); //抽象方法,没有{}括起来的方法体
public void call(){}.     //空方法

使用抽象类

写一个子类继承抽象类,重写抽象方法
虽然不能直接new一个抽象类,但可以先声明一个抽象类变量,再用这个变量指向其子类对象

抽象类名 a;
a = new 子类名();

五.接口

接口规定一批类必须提供某些方法,但不提供实现方法
不能用final关键字修饰接口

定义接口

接口是隐性抽象的,不必使用abstract
用关键字interface定义

访问符 interface 接口名  {
//接口定义的只能是静态常量
int a = 5;
//接口定义的普通方法只能是public的抽象方法
void display();
//接口中定义默认方法,用default修饰
default void print(int b){}
//接口中定义类方法,用static修饰
static void del(){}

}

注意:
访问符可以是public或默认,默认是采用包权限访问控制,即在相同包内才可以访问该接口
成员变量被隐含地声明为public static final,属性只能是静态常量
接口中的方法被隐形指定为public absrtact
接口定义的方法只能是定抽象方法,默认方法,类方法
接口内定义的常量和方法默认为public,可以不写

实现接口

用implements实现接口
一个类可实现多个接口,且必须实现接口中定义的所有抽象方法,否则该类必须定义为抽象类
语法格式:

访问符 class implements 接口1,接口2{

}
public static void main (String[]args){
//先声明一个接口类型的变量,new一个该接口实现类的实例对象,并将其引用赋值给变量
接口名 变量名 = new 接口实现类();
//调用接口的默认方法,必须通过实例对象来调用
变量名.默认方法();
//调用接口的类方法
接口名.类方法();
//声明接口实现类的变量,并实例化该类型对象
接口实现类名 变量名 = new 接口实现类名();
}

接口的继承

接口可以继承多个接口,不能继承类
使用interface可以声明一个接口:

interface Person {
    void run();
    String getName();
}

属性只能是常量

一个类可以实现多个interface,例如:

class Student implements Person, Hello { // 实现了两个interface
    ...
}

六.核心类

字符串类

每个用双引号括起来的字符串都是String类的一个实例

七.内部类

java允许在一个类的类体里再定义一个类,该情况下外面的类叫外部类,里面的叫内部类
内部类可以访问其所在内部类的所有属性

成员内部类

在外部类的内部定义一个类

静态内部类
非静态内部类

局部内部类

匿名内部类

final class就不能被别的类继承

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值