Java进阶学习|Day1.面向对象

面向对象

了解面向对象

定义

面向对象思想是一种程序设计思想,我们在面向对象思想的指引下,使用java语言去设计、开发计算机程序。这里的对象泛指现实中一切事物,每种事物都具备自己的属性和行为。

特点

  1. 面向对象是一种符合人们的思考习惯的思想。
  2. 面向对象的出现,就是为了将复杂的问题简单化。
  3. 面向对象的出现,将程序员从执行者转变为了指挥者。

优点

可以设计出低耦合的系统,使系统更加灵活,更易于维护。

两个关键点

类是一组属性和行为的集合。可以看成是一类事物的模版,使用事物的属性特征和行为特征来描述该事物。

属性:就是该事物的状态信息。

行为:就是该事物能做什么。

  1. 对象

对象是一类事物的具体体现。对象是类的一个实例,必然具备该类事物的属性和行为。

类是对象的抽象化,对象是类的实例化。

面向对象的三大特征

封装

定义

封装可以被认为是一个保护屏障,放置该类的代码和数据被其他类随意访问。要访问该类的数据,必须通过指定的方式。适当的封装可以让代码更容易理解和维护,也加强了代码的安全性。

原则

将属性隐藏起来,若要访问某个属性,通过公共方法对齐访问

使用步骤

  1. 使用private关键字来修饰成员变量。
  2. 对需要访问的成员变量,提供对应的一对getXxx()方法和setXxx()方法。

关键字

  1. private关键字:private是一个权限修饰符,代表最小权限,可以用来修饰成员变量和成员方法。被private修饰后的成员变脸和成员方法,只有在本类中才能访问。
  2. this关键字:this代表所在类的当前对象的引用(地址值),即对象自己的引用。方法被哪个对象调用,方法中的this就代表那个对象。即谁在调用,this就代表谁。

构造方法

java中的构造方法是一种特殊的方法,用来初始化对象。当一个对象被创建时,构造方法用来初始化该对象,给对象的成员变量赋初始值。以下是他的特点。

  1. 函数名与类名相同
  2. 不用定义返回值类型
  3. 没有具体的返回值

继承

定义

就是子类继承父类的属性和行为,使子类对象具有和父类相同的属性和行为。子类可以直接访问父类中的非私有的属性和行为。

优点

  1. 提高代码的复用性
  2. 类与类之间产生了关系,是多态的前提。

关键字

  1. super:代表父类的存储空间标识(可以理解为父类的引用)
  2. this:代表当前对象的引用(谁调用就代表谁)

特点

  1. java只支持单继承,不支持多继承
  2. java支持多层继承(继承体系)
  3. 最顶层父类是Object类。所有的类都默认继承Object,作为父类
  4. 子类和父类是一种的相对的概念,父类也可能是另一个父类的子类。(继承体系)

多态

定义

是指同一行为,具有多个不同表现形式。

前提

  1. 继承或者实现(二选一)
  2. 方法的重写:不重写,也就没有意义
  3. 父类引用指向子类对象(格式体现)

体现

父类类型 变量名 = new 子类对象;

变量名.方法名();

编译看左边,运行看右边

好处

实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展性和便利性。

xxxxx(父类类型 变量名),

传入一个子类对象。

使用

  1. 前提:多态对象把自己看做是父类类型
  2. 成员变量:使用的是父类的
  3. 成员方法:由于存在重写现象,所以使用的是子类的
  4. 静态成员:随着类的加载而加载谁,谁调用就返回谁的

转型

  1. 向上转型

多态本身就是子类类型向父类类型向上转换的过程,这个过程是默认的。

父类类型 变量名 = new 子类类型();

//如:Animal a = new Cat();

通俗来讲:花木兰替父从军,大家都把花木兰看做她爸,但是实际从军的是花木兰,而且,花木兰只能做她爸能做的事,在军营里是不可以化妆的。

  1. 向下转型

父类类型向子类类型向下转换的过程,这个过程是强制的。

子类类型 变量名 = (子类类型) 父类变量名;

// 如: Cat c =(Cat) a;

通俗来讲:花木兰打仗结束,就不需要再看做是她爸了,就可以”对镜贴花黄”了

  1. 使用

当使用多态方法调用方法时,首先检查父类中是否有该方法,如果没有,则编译是错误。也就是说,使用向上转型的的调用方法时,不能调用子类拥有,而父类没有的方法。

这也是多态给我们带来的一点“小麻烦”。所以,想要调用子类特有的方法,必须向下转型。

  1. 异常
public class Test {
	public static void main(String[] args) {
		// 向上转型
		Animal a = new Cat();
		a.eat(); // 调用的是 Cat 的 eat
		// 向下转型
		Dog d = (Dog)a;
		d.watchHouse(); // 调用的是 Dog 的 watchHouse 【运行报错】
	}
}

这段代码可以通过编译,但是运行时,却报出了 ClassCastException ,类型转换异常!这是因为,明明创建了Cat类型对象,运行时,当然不能转换成Dog对象的。这两个类型并没有任何继承关系,不符合类型转换的定义。

为了避免ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验。

变量名 instanceof 用于判断数据类型

如果变量属于该数据类型,返回true

如果变量不属于该数据类型,返回false

public class Test {
	public static void main(String[] args) {
		// 向上转型
		Animal a = new Cat();
		a.eat(); // 调用的是 Cat 的 eat
		// 向下转型
		if (a instanceof Cat){
			Cat c = (Cat)a;
			c.catchMouse(); // 调用的是 Cat 的 catchMouse
		} else if (a instanceof Dog){
			Dog d = (Dog)a;
			d.watchHouse(); // 调用的是 Dog 的 watchHouse
		}
	}
}

static关键字

定义

它可以用来修饰成员变量和成员方法,被修饰的成员是属于类的,而不是单单属于某个对象。也就是说,既然属于类,就可以不靠创建对象来调用

使用

  1. 静态变量(类变量)

当static修饰成员变量时,该变量称为类变量。该类的每个对象都共享同一个类变量的值。任何对象都可以更改该类变量的值,单页可以在不创建该类对象的情况下对类变量进行操作。

public class Student {
	private String name;
	private int age;
	// 学生的id
	private int sid;
	// 类变量,记录学生数量,分配学号
	public static int numberOfStudent = 0;
	public Student(String name, int age){
		this.name = name;
		this.age = age;
		// 通过 numberOfStudent 给学生分配学号
		this.sid = ++numberOfStudent;
	}
	// 打印属性值
	public void show() {
		System.out.println("Student : name=" + name + ", age=" + age + ", sid=" + sid );
	}
}
public class StuDemo {
	public static void main(String[] args) {
		Student s1 = new Student("张三", 23);
		Student s2 = new Student("李四", 24);
		Student s3 = new Student("王五", 25);
		Student s4 = new Student("赵六", 26);
		s1.show(); // Student : name=张三, age=23, sid=1
		s2.show(); // Student : name=李四, age=24, sid=2
		s3.show(); // Student : name=王五, age=25, sid=3
		s4.show(); // Student : name=赵六, age=26, sid=4
	}
}
  1. 静态方法(类方法)

当static修饰成员方法时,该方法称为类方法。静态方法在声明中有static,建议使用类名来调用,而不需要创建类的对象,调用方式很简单。

//为上边Student类补充一个静态方法
public static void showNum() {
	System.out.println("num:" + numberOfStudent);
}
  1. 静态代码块

也就是定义在成员位置,使用static修饰的代码块{}。

位置处于类中方法外。

执行:随着类的加载而执行且执行一次,优先于main方法和构造方法的执行。

public class Game {
	public static int number;
	public static ArrayList<String> list;
	static {
		// 给类变量赋值
		number = 2;
		list = new ArrayList<String>();
		// 添加元素到集合中
		list.add("张三");
		list.add("李四");
	}
}
  1. 静态调用
public static void main(String[] args) {
	// 访问类变量
	System.out.println(Student.numberOfStudent);
	// 调用静态方法
	Student.showNum();
}

final关键字

定义

举个例子,我们能不能随意修改继承API中提供的类,或者改写其内容?显然是不合适的。为了避免这种随意改写的情况,java提供了final关键字,用来修饰不可改变的内容。

修饰什么

  1. 修饰类
final class 类名 {
}

作用:

查询API发现像 public final class String 、 public final class Math 、 public final class Scanner等,都是被final修饰的,此类不能被修改。

并且被 final 修饰的类不能被继承

  1. 修饰方法
修饰符 final 返回值类型 方法名(参数列表){
	//方法体
}

作用:

继承带有 final 修饰的方法时不能重写,否则编译时就会报错。

  1. 修饰变量
  • 修饰局部变量

    • 变量类型为基本类型

    基本类型的局部变量,被final修饰后,只能赋值一次,不能再更改。

    public class FinalDemo1 {
    	public static void main(String[] args) {
    		// 声明变量,使用final修饰
    		final int a;
    		// 第一次赋值
    		a = 10;
    		// 第二次赋值
    		a = 20; // 报错,不可重新赋值
    		// 声明变量,直接赋值,使用final修饰
    		final int b = 10;
    		// 第二次赋值
    		b = 20; // 报错,不可重新赋值
    	}
    }
    
    • 变量类型为引用类型

    引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能再更改。但是不影响对象内部的成员变量值的修改。

    public static void main(String[] args) {
    	// 创建 User 对象
    	final User u = new User();
    	// 创建 另一个 User对象
    	u = new User(); // 报错,指向了新的对象,地址值改变。
    	// 调用setName方法
    	u.setName("张三"); // 可以修改
    }
    
  • 修饰成员变量

    初始化方法有两种

    • 显示初始化

      public class User {
      	final String USERNAME = "张三";
      	private int age;
      }
      
    • 构造方法初始化

    public class User {
    	final String USERNAME ;
    	private int age;
    	public User(String username, int age) {
    		this.USERNAME = username;
    		this.age = age;
    	}
    }
    

    被final修饰的常量名称,一般都有书写规范,所有字母都大写

Object类

定义

java.lang.Object 类是Java语言中的根类,即所有类的父类。它中描述的所有方法子类都可以使用。在对象实例化的时候,最终找的父类就是Object。

如果一个类没有特别指定父类, 那么默认则继承自Object类。

成员方法

  1. toString()

toString方法返回该对象的字符串表示,其实该字符串内容就是

对象的类型+@+内存地址值

由于toString方法返回的结果是内存地址,而在开发中,经常需要按照对象的属性得到相应的字符串表现形式,因此也需要去重写它。

public class Person {
	private String name;
	private int age;
	@Override
	public String toString() {
		return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
	}
	// 省略构造器与Getter Setter
}
  1. equals()

equals()方法用来指示其他某个对象是否与此对象”相等“。

如果没有覆盖重写equals方法,那么Object类中默认进行==运算符的对象地址比较,只要不是同一个对象,那么结果必然为false。

如果希望进行对象内容的比较,即所有或指定的部分成员变量相同就判定两个对象相同,则可以覆盖重写equals方法。

import java.util.Objects;
public class Person {
	private String name;
	private int age;
	@Override
	public boolean equals(Object o) {
		// 如果对象地址一样,则认为相同
		if (this == o)
		return true;
		// 如果参数为空,或者类型信息不一样,则认为不同
		if (o == null || getClass() != o.getClass())
		return false;
		// 转换为当前类型
		Person person = (Person) o;
		// 要求基本类型相等,并且将引用类型交给java.util.Objects类的equals静态方法取用结果
		return age == person.age && Objects.equals(name, person.name);
	}
}

与==的区别:

  1. 对于基本类型,==比较的是值。
  2. 对于引用类型,==比较的是地址。
  3. equals不能用于基本类型的比较。
  4. 如果没有重写equals,equals就相当于==。
  5. 如果重写了equals方法,equals比较的是对象的内容。
  1. hashCode()

返回的是一串由JVM给不同对象分配的整数类型的哈希码值。

每个对象的哈希码值都不相同,除非重写hashCode()方法。

  1. getClass()

返回对象的运行时的类,简单来说就是获取当前对象所属的字节码文件对象。

  1. finalize()

用于垃圾回收,我们不用手动的去调用,而是由JVM来调用。

当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。

  1. Objects类

它提供了一些方法来操作对象,它由一些静态的实用方法组成,这些方法是null-save(空指针安全的)或者null-tolerant(容忍空指针的),用于计算对象的hashCode,返回对象的字符串表示形式,比较两个对象的。

在比较两个对象的时候,Object的equals方法容易抛出空指针异常,而Objects类中的equals方法就优化了这个问题。

public static boolean equals(Object a, Object b) :判断两个对象是否相等。

package包

定义

写的class类成千上万,为了我们的Java文件不重叠,于是有了包的概念。

特点

  1. 对类文件进行分类管理
  2. 给类提供多层命名空间
  3. 包的定义是用一个关键字package包名
  4. 写在程序的第一行
  5. 包也是一种封装的形式
  6. 定义包名的字母都是小写

导包

当我们用到某个包的类时,用关键字import把包的所有类给导入。这样就不用每次通过包名.类名去调用了,方便了操作,简化了书写。

当导入不同包中的有同名类时,必须指定包名。

为了不至于类名重复,可以使用url来完成定义是唯一的。 (url:域名)

内部类

定义

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。

分类

  1. 成员内部类

是定义在类中方法外的类。

class Car { //外部类
	class Engine { //内部类
	}
}

访问特点:

内部类可以直接访问外部类的成员,包括私有成员。

外部类要访问内部类的成员,必须建立内部类的对象。

外部类名.内部类名 对象名 = new 外部类型().new 内部类型();

  1. 匿名内部类

是内部类的简化写法。它的本质是一个带具体实现的父类或者父接口的匿名的子类对象。开发中,最常用的内部类就是匿名内部类。

特点:

当使用一个接口时,需要以下几步操作:

定义子类->重写接口中的方法->创建子类对象->调用重写后的方法

通俗来讲,我们最终的目的,只是为了调用这个方法,那么是不是可以简化一下,将以上四步合成一步?匿名内部类就是做这样的快捷方式。

前提:

匿名内部类必须继承一个父类或者实现一个父接口

使用方式:

定义接口

public abstract class FlyAble{
	public abstract void fly();
}

创建匿名内部类,并调用

public static void main(String[] args) {
	/*
	1.等号右边:是匿名内部类,定义并创建该接口的子类对象,此时是需要具体实现一个父类或者父接口的,
	2.等号左边:是多态赋值,接口类型引用指向子类对象
	*/
	FlyAble f = new FlyAble(){
		public void fly() {
			System.out.println("我飞了~~~");
		}
	};s
	//调用 fly方法,执行重写后的方法
	f.fly();
}
  • 16
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值