Java基础复习 【面向对象】

【简介】

1. Java面向对象学习的三条主线:

  1. Java类以及类的成员:属性、方法、构造器、代码块、内部类;
  2. 面向对象的三大特征:封装性、继承性、多态性、(抽象性);
  3. 其他关键字:this、super、static、final、abstract、interface;

2. 面向过程POP与面向对象OOP的比较:

面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做;
面向对象:强调具备了功能的对象,以类/对象作为最小单位,考虑谁来做;
万事万物皆对象:1. 在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化来调用具体的功能。2. 在涉及Java语言与前端Html、后端的数据库交互时,前后端的结构都体现为类和对象。

一、类的成员

1. 类的属性

2. 类的方法

1. 方法的重载:
定义:在同一个类中,允许存在一个以上的同名方法,只要它们参数个数和参数类型不同即可。

两同一不同:同一个类,相同方法名,参数列表不同:参数个数不同、参数类型不同。
:返回类型的不同不是区分重载的条件。

面试题:方法的重载与重写的区别?
:两者并没有什么关系。重载是静态绑定,多态是动态绑定。

2. 方法的重写
定义:子类继承父类以后,可以对父类中同名参数的方法进行覆盖操作。

重写的规定:① 子类重写的方法方法名和形参列表 与 父类被重写的方法的方法名和形参列表相同。
② 子类重写的方法的权限修饰符 不小于 父类被重写的方法的权限修饰符(:子类中不能重写父类中声明为private权限的方法)。
③ 父类被重写的方法的返回值类型是void和基本数据类型,则子类重写的方法的返回值类型只能相同;如果是A类型,则可以是A类型及其子类。

3. 可变个数的形参:
下面两个效果一样,不能构成重载。在方法形参中,只能声明一个可变个数形参,只能位于末尾。

JDK5.0 以前:采用数组形参来定义方法,传入多个同一类型的变量。
public static void test(int a,String[] books);

JDK5.0:采用可变个数形参来定义方法,传入多个(0-N)同一类型变量。
public static void test(int a,String ...books);
books的调用还是按照数组来使用。

4. 方法参数的传递机制:(重要)

形参:方法定义时,声明的参数;
实参:方法调用时,实际传递的数据;
传值与传地址:基本数据类型的赋值是将实际的值复制,引用数据类型赋值是地址值。(例:交换值的方法实现–需要引用类型)

3. 构造器

也称构造方法。一个类中多个构造器构成重载。

1. 构造器的作用:

创建对象:new + 构造器。如果没有显式的定义类的构造器,则系统提供一个空参的构造器。一旦我们显式的定义了类的构造器后,系统将不会提供默认的空参构造器。
给对象进行初始化:一般是初始化对象的信息。

4. 代码块

代码块也叫初始化块。
作用:用来初始化类和对象。

① 代码块如果有修饰的话,只能使用static。可分为静态代码块 vs 非静态代码块

// 1. static 静态代码块  ----> 初始化类的信息。
static{ // *随着类的加载而执行,只执行一次
	System.out.println("我是随着类的加载而执行的");
}

// 2. 非静态代码块 ----> 可以在创建对象的时候对对象的属性进行初始化。
{ // *随着对象的创建而执行,每创建一个对象就会执行一次,可执行多次
	System.out.println("我是随着对象的创建而执行的");
}

② 一个类中可以定义多个静态代码快,执行顺序从上往下。
③ 静态代码块的执行先于非静态的代码快。

5. 内部类

内部类的分类: 成员内部类 vs 局部内部类(方法内、代码块内、构造器内)。

class Person{
	String name;
	int age;
	void eat(){}

	// 1. 非静态成员内部类
	class Dog{
		String name;
		void f(String name){
			Person.this.eat(); // 【调用外部非静态方法】
			System.out.println(name); // 方法的形参
			System.out.println(this.name); // 内部类的属性
			System.out.println(Person.this.name); // 外部类的属性
		}
	}

	// 2. 静态成员内部类
	static class Bird{}

	// 3. 局部内部类
	public void method(){
		class AA{}
	}
}
// 测试
public InnerClassTest{
	public static void main(String []args){
		// 1.创建Dog实例(静态的成员内部类)
		Person.Dog dog = new Person.Dog();
		//2. 创建Bird实例(非静态的成员内部类)
		Person p = new Person();
		Person.Bird bird = p.new Bird(); // 看清楚
	}
}

内部类使用的题目:返回一个实现了Comparable接口的类对象

public Comparable getComparable(){
	class MyComparable implements Comparable{
		@Override
		public int compareTo(Object o){
			return 0;
		}
	}
	return new MyComparable();
}

二、面向对象的三大特征

1. 封装与隐藏性

封装性:通过4种修饰符来修饰类以及类的内部结构,改变被调用时的可见性的大小,使得有些可见有些不可见。

程序设计追求:高内聚、低耦合;
高内聚:类的内部数据操作细节自己完成,不允许外部干涉。
低耦合 :仅对外部暴露少量的方法用于使用。

问题引入:对对象的属性进行赋值操作受到属性的数据类型和存储范围的制约。

1. 封装性的体现:(某个方面)

  1. 将类的属性私有化,同时提供public的get与set方法。
  2. 不对外暴露的私有方法。
  3. 单例模式。

2. 四种权限修饰符

封装性的体现,需要权限修饰符来配合。(如下从小到大)
private:类内部可用。
缺省:类内部、同一个包内可用。
protected:类内部、同一个包内、不同包的子类可用。
public:类内部、同一个包内、不同的包的子类、同一个工程可用。

4种权限可以用来修饰类的内部结构:属性、方法、构造器、内部类。
修饰的话,只能使用:缺省和public。

2. 继承性

1. 继承性的好处:

① 减少了代码的冗余,提高代码的复用;
② 便于功能扩展;
③ 为多态性提供了前提;

2. 继承性的格式

class A extends B
private修饰的属性或方法也是继承了的,只不过由于封装性的影响,不能直接调用。

3. Java中继承性的规定

① 一个父类可以有多个子类来继承,一个子类只能有一个父类(java中单继承性,不同于C++的多继承)。
② 可以有多重继承(直接父类 -> 间接父类),子类继承父类以后,就获取了所有父类中声明的属性和方法。
③ 如果我们没有显式的继承一个父类的话,那么该类继承与java.lang.Object类。

3. 多态性

定义理解:一个事物的多种形态;多态是一个运行时行为: ( 如 声明参数为引用类型时,实际参数可以根据需要传递其子类,子类种类是可以多个的,所有只有在运行时才能知道结果)。

何为多态性:对象的多态性。

多态性的使用前提:①类的继承关系 ; ② 方法的重写;③ 对象的多态性只适用于方法,不适用属性。

① 对象的多态性:父类的引用对象指向子类的对象 或 (子类的对象赋给父类的引用),如Person p = new Man();其中p只能调用父类中有的方法,子类中特有的方法是不能调用的。(编译看左边,运行看右边)。
② 多态性的使用:当调用父类参数同名的方法时,实际执行的是子类重写的方法。----> 虚拟方法调用。如public void func(Person p){}+func(new Man()) —> 用子类对象赋值给父类引用。

虚拟方法调用: 子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据给它的不同子类对象,动态调用属于子类的该同名方法。

向下转型的使用:

有了对象的多态性以后,内存中实际加载了子类中特有的属性和方法的,但是由于变量声明的是父类类型,导致编译时只能调用父类中声明的属性和方法,其中子类特有的属性和方法是不能调用的。

怎样才可以调用:使用强制类型转换(强制类型转换可以会出现ClassCastException异常)。 —> ( 向下转型 );
向上转型也就是多态。

三、主要关键字

1. this关键字

① 可以理解为当前对象 或 当前正在创建的对象。
② 可以用来修饰或调用属性、方法、构造器。通常情况下,我们都是省略this.,但在形参和类的属性同名时,就需要使用this.来区分。
this():在类的构造器中,可以显式的使用this(形参列表)方式,调用本类中指定的其他构造器。
规定this(形参列表)必须声明在当前构造器的首行。构造器内部只能提供一个this()。

this.xx属性:先从子类中寻找属性xx,如果没有找到才会向上在父类中国寻找(就近原则)。

2. package、import关键字

package使用:

① 为了更好的实现项目中类的管理,提供了包的概念。使用package声明类或接口所属的包,声明在源文件的首行。
② 命名:每.一次表示一级文件目录。

import使用:

① 在源文件中显式的使用import结构导入指定包下的类、接口。
② 如果使用的类或者接口在java.lang下,可以省略import,直接使用。
③ 如果原文件中使用了不同包下的同名类,那么至少有一个需要全类名来声明。
④ 使用xxx.*方式表明可以调用xxx包下的所有结构,但是如果使用xxx子包下的结构,则仍需要显式导入。
import static导入指定类或者接口`中·的静态结构(方法+属性)。

super使用:

① 可以在子类的构造器中显式的使用"super(形参列表)"(写在首行)的方式,调用父类中声明的指定的构造器;
② 其中"this(形参列表)“和"super(形参列表)”只能二选一;默认首行都有一个"super()";
③ 虽然在创建子类对象时,调用了弗雷德构造器,但自始至终就只创建了一个对象,即为new的子类对象

instanceof使用:
x instanceof A :检验x是否为类A的对象,返回值为boolean型。

可用于决解强制类型转换可以会出现ClassCastException异常;
eg :if(p instanceof Man){}

3. static的使用

static可以用来修饰:属性、方法、代码块、内部类。

使用static修饰属性:

① 属性按照是否使用static修饰分为静态变量(类变量) vs 非静态变量(实例变量)。
② 实例变量:创建类的多个对象时,每个对象都独立拥有一套非静态属性。
③ 静态变量:多个对象共享同一个静态变量。
④ 静态变量随着类加载而进行加载,静态变量的加载要早于对象的创建。可以通过类.*调用。

使用static修饰方法:

① 随着类的加载而加载,可以通过类.*的方式进行调用。
静态方法中只能调用静态的方法和属性。非静态的方法中既可以调用静态方法属性也可以调用非静态方法属性。
③ 静态方法内,不能使用this、super关键字。

3.1 单例(Singleton)设计模式

设计模式:是大量的时间中总结和理论化之后优选的代码结构、编程风格、以及决解问题的思考方式。

单例设计模式:
定义:采用一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例。

如何实现饿汉式:
① 私有化构造器;
② 内部创建类的static对象;
③ 提供static的公共方法,返回类的实例对象;

class Bank(){
	//① 私有化构造器;
	private Bank(){}
	//② 内部创建类的static对象;
	private static Bank instance = new Bank();
	//③ 提供static的公共方法,返回类的实例对象;
	public static Bank getInstance(){ 
		return instance;
	}
}

如何实现懒汉式:
① 私有化构造器;
② 内部声明类的static对象,没有初始化;
③ 提供static的公共方法,返回类的实例对象;

class Bank(){
	//① 私有化构造器;
	private Bank(){}
	//② 内部声明类的static对象,没有初始化;
	private static Bank instance = null;
	//③ 提供static的公共方法,返回类的实例对象;
	public static Bank getInstance(){
		if(instance  == null){ // 判断是否创建过
			synchronized (Bank.class){ // synchronized 决解线程安全问题
				if(instance == null) instance = new Bank();
			}
		}
		return instance;
	}
}

区分饿汉式和懒汉式
饿汉式:坏处 - 对象加载时间过长。 好处 - 饿汉式是线程安全的。
懒汉式:好处 - 延迟对象的创建。 坏处 - 上面写的懒汉式是不安全的。

4. final的使用

final可以用来修饰:类、方法、变量。

① final修饰类:此类就不能被其他类继承。
② final修饰方法:此方法就不能被重写。
③ final修饰变量:此变量 = 常量。
final修饰属性可以考虑进行赋值位置:显式初始化、代码块中初始化、构造器中初始化。

5. 抽象类 与 抽象方法

abstract可以用来修饰:类、方法。

① 抽象类:是不可以实例化。但是抽象类中还是一定有构造类的,便于子类实例化的调用。
② 抽象方法:只有方法的声明,没有方法体。包含抽象方法的类一定是抽象类,反之抽象类不一定有抽象方法。public abstract void show();
注:若子类重写了父类中所有的抽象方法,则此子类可以实例化对象。若子类没有重写父类中的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰。
③ abstract不能用来修饰属性、构造器等结构,也不能用来修饰private方法、静态方法、final的方法。

6. 接口

使用interface来定义,java中接口和类是并列的结构。
接口中不能定义构造器,也就意味着接口不能实例化。

定义接口:
① JDK7及以前:只能定义全局常量和抽象方法。
全局常量:public static final xxx,但是书写时可以省略不写。
抽象方法:public abstract xxx

② JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法。
③ 接口通过让类去实现implements的方法来使用,如果实现覆盖了接口中所有的抽象方法,则此实现类就可以实例化,如果 实现类没有覆盖接口中所有的抽象方法,则此实现类为一个抽象类。
④ java类可以实现多个接口,弥补了java单继承的局限性。
格式:class AA extends BB implements CC,DD,EE{}

interface Flyable{
	// 1. 全局常量
	public static final int MAX_SPEED = 7900;
	int MIN_SPEED = 1; // 省略了public static而已

	// 2. 抽象方法
	public abstract void fly();
	void stop(); // 省略了 public abstract 

	// 3. 静态方法:接口中定义的静态方法只能通过接口来调用。
	public static void method1(){};

	// 4. 默认方法:通过实现类可以调用接口中的默认方法。默认方法也是可以重写的。
	public default void method2(){};
}
// 访问全局常量:可以直接  接口名.*
System.out.println(Flyable.MAX_SPEED);

⑤ 接口 与 接口之间可以多继承。
⑥ 类优先原则:如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的默认方法,那么在子类没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法。
⑦ 接口冲突:如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,那么在实现类没有重写此方法的情况下,报错 —> 重写此方法可决解。

接口的使用:
① 接口的使用也满足多态性;
② 接口实际上就是定义了一种规范;
③ 开发中,体现面向接口编程;


四、扩展知识

1. JavaBean

JavaBean是一种Java语言写成的可重用组件。

所谓JavaBean,是指符合如下标准的Java类:1.类是公共的;2.有一个无参的公共构造器;3.有属性,且有对应的get、set方法。

2. MVC设计模式

MVC(model view controller)是常用的设计模式之一,将整个程序分为三个层次:视图模式层控制器层数据模型层

常用的命名:
模型层:主要处理数据。

  1. 数据对象封装:model.bean/domain;
  2. 数据库操作类:model.dao;
  3. 数据库:model.db;

控制层:处理业务逻辑。

  1. 应用界面相关:controller.activity;
  2. 存放fragment:controller.fragment;
  3. 显示列表的设配器:controller.service;
  4. 服务器相关的:controller.service;
  5. 抽象的基类:controller.base;

视图层:显示数据。

  1. 相关工具类:view.utils;
  2. 自定义视图:view.ui;

3. Object类的使用

定义:Object是所有java类的根父类。

属性:无
方法
equals():对象比较,只能适用于引用数据类型
toString():对象打印调用
getClass():
hashCode():取得Hash码
clone():
finalize():
wait():
notify():
notifyAll():

1. equals()使用
Object类没用重写equals()以前比较的是地址值。

==:基本数据类型比较的是内容,引用数据类型比较的是地址值。
equals():Object类中equals方法与==效果是一样的。
像String 、Data、File、包装类都重写了Object类中的equals方法,重写以后比较的不是地址值是否相同,而是比较的是实体内容是否相同。

String s1="AA",s2="AA"; s1==s2//true,因为"AA"存在常量池中
String s1=new String("AA"), s2=new String("AA"); s1==s2 // false

自定义类中重写equals方法: 使其比较对象的实体内容

// 手写如下,实际开发当中可以直接开使用发工具自动生成
public boolean equals(Object obj){
	if(this == obj) return true; // 两个是否为同一个对象。地址值相同
	if(obj instanceof Person){
		Person p = (Person)obj; // 强制类型转换
		if(this.age == p.age && this.name.equals(p.name)) return true;
		else return false;
	}
}

2. toString()使用

① 当我们输出一个对象的引用时,实际上就是调用当前对象的toString()方法。

4. 包装类(Wrapper)的使用

定义:针对八种基本数据类型定义相应的引用类型 — 包装类。
前六个数值型类都有一个父类Number。

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
booleanBoolean
charCharacter

基本数据类型、包装类、String类三者的相互转换

// 1. 基本数据类型 ---> 包装类
Integer num = new Integer(10);
Float f = new Float("12.3");
// 2. 包装类 --->基本数据类型 : 调用包装类的xxxValue()
Integer num = new Ineter(20);
int n = num.intValue();

// JDK5.0 新特性:自动装箱,自动拆箱
// 注 - 自动装箱: 
int num = 10;
Integer in = num; 
// 注 - 自动拆箱:
int num1 = in;

// 3. 基本数据类型、包装类 ---> String类型
方式一:连接运算
String s = 10 + "";

方式二:使用String重载的valueOf()方法
String s = String.valueOf(12.3f);
Double d = new Double(12.3);
String s = String.valueOf(d);

// 4. String类型 ---> 基本数据类型、包装类
方式:调用包装类的 parseXXX() 方法
String s = "123";
int num = Integer.parseInt(s);
String s = "true";
boolean b = Boolean.parseBoolean(s);

面试题:

Integer i = new Integer(1);
Integer j = new Integer(1);
i == j // 为false

Integer m = 1;
integer n = 1;
m == n // 为true -> Integer内部定义了IntegerCache结构,其中定义了Integer[],
		// 保存了 -128 ~ 127 范围的数。

Integer x = 128; // 128不在范围内,new了一个对象
Integer y = 128;
x == y // 为true

5. Java中的Junit单元测试

步骤:
① 选中当前工程 - 右击 - build path - add libraries - Junit 4 ;
② 创建Java类,进行单元测试。
测试类要求:此类是public的;此类需要提供公共的无参的构造方法。
③ 此类中声明单元测试方法。
测试方法要求:方法权限为public,返回值为void,没有形参。
④ 此单元测试方法上需要声明注解:@Test,并在单元测试类中导入import org.junit.Test。


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

战胜.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值