JavaSe学习笔记day04(面向对象三)

面向对象特性——多态性

一 多态性 : 一类事物的多种形态

二 何谓多态性:
广义上 : ①方法的重写,方法的重载 ②子类对象的多态性
狭义上 : 子类对象的多态性

三 子类对象的多态性 :父类的引用指向子类的对象。

四 多态的前提 :1.要有继承关系 2.要有方法的重写 3.父类的引用指向子类的对象

注意:属性没有多态性。
Person p = new Woman();//虚拟方法调用 - 编译看左边,运行看右边
p.show();//运行的事Woman的对象show,如果没有就运行Person里面的对象show
p.say();

五、思考 : 在多态的前提下如何调用子类对象中特有的属性和方法?
可以采用向下转型的方式 :使用强制类型转换符

Woman w = (Woman)p;//注意 : p指向的对象必须是woman的对象才可以这么做
w.buy();
System.out.println(w.name);

使用场景:Man m = (Man) p; 发生错误 : ClassCastException- 类型转换异常为了解决类型转换异常可以在向下转型时使用instanceof :
a instanceof Woman : a对象是否是Woman的一个实例(对象),如果是返回true,否则返回false
Create <- Person <- Woman/Man
p指向的对象 instanceof 对象所在的类及父类 : true
p指向的对象 instanceof 对象所在类的子类 : false

Object类

一.概述
1.Object类是所有类的父类
2.如果一个类没有显示继承其它类那么默认继承Object类
3.Obejct只有一个空参的构造器
4.Object中有11个方法,其中三个wait方法是重载方法
equals() / toString() / getClass() /hashCode() / clone() / finalize() / wait() 、 notify()、notifyAll()等

equals方法:

一 概述
1)Object中的equals方法:

  public boolean equals(Object obj) {
	return (this == obj);
  }   

2)像String,Date等核心类库基本上都重写了equals方法,用来比较内容

3)自定义类如果没有重写equals方法那么调用的是Object中的equals方法用来比较内容。

但是我们自定义类的时候通常都会重写equals方法,用来比较内容.

二、 ==和 equals的区别是什么?

1)equals()方法的使用:

1.是一个方法,而非运算符

2.只能适用于引用数据类型

3.如果没有重写Object中的方法比的是地址值,如果重写了equals方法那么通常比较的是内容

4.String中的equals方法是用来比较内容的

2)== :运算符

1.可以使用在基本数据类型变量和引用数据类型变量中

2.如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。(不一定类型要相同)

如果比较的是引用数据类型变量:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体

补充: == 符号使用时,必须保证符号左右两边的变量类型一致。
说明:Object类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体

toString方法 :

一 Object中的toString方法

public String toString() {
    	return getClass().getName() + "@" + Integer.toHexString(hashCode());
	  }

二 像String,Date等核心类库基本上都重写了toString方法,用来输出对象中的内容。

三 自定义类如果没有重写toString方法那么调用的是Object中的toString方法用来输出对象的地址值。

但是我们自定义类的时候通常都会重写toString方法,用来输出对象的内容.

注意 :当我们输出对象的名字时,默认调用的是当前对象的toString方法

包装类

包装类:针对八种基本数据类型定义相应的引用类型—包装类(封装类)
在这里插入图片描述
掌握的:基本数据类型、包装类、String三者之间的相互转换

在这里插入图片描述

/*
 * 包装类
 */
public class WrapperTest {
	/*
	 * 基本数据类型 -> 包装类 : 通过包装类的构造器
	 */
	@Test
	public void test2(){
		int a = 10;
		Integer integer = new Integer(a);
		Integer inte = new Integer(a);
		System.out.println(integer);
	
		boolean bo = true;
		Boolean boo = new Boolean(bo);
		System.out.println(boo);
	}
	/*
	 * 包装类 -> 基本数据类型 : 包装类的对象.xxxValue()
	 */
	@Test
	public void test3(){
		Integer integer = new Integer(30);
		int number = integer.intValue();
		System.out.println(number);
		
		Boolean boo = new Boolean(true);
		boolean booleanValue = boo.booleanValue();
		System.out.println(booleanValue);
	}
	/*
	 * 自动装箱:将基本数据类型直接赋值给包装类
	 * 自动拆箱: 将包装类的对象直接赋值给基本数据类型
	 */
	@Test
	public void test4(){
		//自动装箱
		Integer number = 20;
		//自动拆箱
		int num = number;
		//调用方法
		info(20);//自动装箱
		//下面使用了 : 1.自动装箱   2.多态
		Object obj = true; //自动装箱 :1.true自动装箱  2.将对应的包装类的对象再赋值给obj
	}
	public void info(Object obj){
		System.out.println(obj instanceof Integer);
	}
	/*
	 * 包装类,基本数据类型 -> String
	 * 包装类 -> String :  通过toString方法
	 * 基本数据类型 -> String : 1.字符串拼接   2.String.valueOf()
	 */
	@Test
	public void test5(){
//		包装类 -> String :  通过toString方法
		Integer integer = new Integer(30);
		String str = integer.toString();
		System.out.println(str);
		
		//基本数据类型 -> String
		int number = 10;
		//第一种方式
		String s = number + "";
		System.out.println(s);
		//第二种方式
		String s2 = String.valueOf(number);
		System.out.println(s2);
	}
/*
	 * String -> 包装类,基本数据类型
	 * String -> 包装类 : 通过包装类的构造器
	 * String -> 基本数据类型 : Xxx.parseXxx() - 第一个Xxx对应的包装类 ,第二个Xxx对应的类型
	 */
	@Test
	public void test6(){
		//String -> 包装类 : 通过包装类的构造器
//		String s = "100a";
//		Integer integer = new Integer(s); //NumberFormatException : 数值格式化异常
//		System.out.println(integer);
		
		//下面的特殊一些 并不会抛异常
		String s = "abc";
		Boolean boo = new Boolean(s);
		System.out.println(boo);
		
		System.out.println("-------------------------------------------------");
		
		//String -> 基本数据类型 : Xxx.parseXxx() - 第一个Xxx对应的包装类 ,第二个Xxx对应的类型
		
		s = "11";
		int number = Integer.parseInt(s);
		System.out.println(number);
		
		s = "12.5";
		double parseDouble = Double.parseDouble(s);
		System.out.println(parseDouble);
	}

	/**
	 *  如果赋值的范围在  -128 ~ 127 那么会从数组中直接取出一个对象。
	 *  如果赋值的范围不在 -128 ~ 127 那么会直接创建一个新的对象
	 */
	@Test
	public void test3(){
	    Integer i = new Integer(1);
	    Integer j = new Integer(1);
	    System.out.println(i == j);//false

	    
	    Integer m = 1;
	    Integer n = 1;
	    System.out.println(m == n);//true

	    Integer x = 128;
	    Integer y = 128;
	    System.out.println(x == y);//false
	}

单例设计模式

在整个项目中某一个类的对象只能创建一个。
一、实现的方式:懒汉式和饿汉式
懒汉式和饿汉式的区别?
懒汉式 :1.线程不安全的 2.延迟了对象的创建时机,一定程度上节省了内存的开销。(懒加载)
饿汉式 :1.线程安全的

//饿汉式
class Bank{
	//1.私有化构造器
	private Bank(){}
	//2.创建一个该类的对象,并使用static修饰
	private static Bank bank = new Bank();
	//3.提供一个公共的方法,用来返回对象。该方法必须是静态方法(可以通过类名调用该方法)。
	public static Bank getInstance(){
		return bank;
	}
}
//懒汉式
class Computer{
	//1.私有化构造器
	private Computer(){}
	//2.提供一个该类的对象的声明
	private static Computer computer = null;
	//3.提供一个公共的方法,并返回对象
	public static Computer getInstance(){
		//4.创建对象
		if(computer == null){
			computer = new Computer();
		}
		return computer;
	}
}
//饿汉式
class Band{
	private Band(){}
	private static Band band = new Band();
	public static Band geInstance(){
		return band;
	}
//懒汉式
static  class Haha{
	private Haha(){};
	private static Haha haha1 = null;
	public static Haha instance(){
		if(haha1 == null){
			Haha haha1 = new Haha();
			return haha1;
		}
		return haha1;
	}
}	
}

使用场景
网站的计数器,一般也是单例模式实现,否则难以同步。
应用程序的日志应用,一般都使用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。
项目中,读取配置文件的类,一般也只有一个对象。没有必要每次使用配置文件数据,都生成一个对象去读取。
Application 也是单例的典型应用
==Windows的Task Manager (任务管理器)==就是很典型的单例模式
==Windows的Recycle Bin (回收站)==也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。

main方法

1.main方法是程序的入口
2.main方法的形参名可以改,其它都不允许修改
3.一个程序只有一个main方法。

代码块

  1. 格式 : {}
  2. 代码块分类 :静态代码块 和 vs 非静态代码块
  3. 注意 : 代码块只能使用static修饰。
    3.1 静态代码块:
    1)静态代码块是随着类的加载而加载的。(类加载只加载一次)
    2)类加载优先于对象的创建。(静态代码块的执行优先于非静态代码块)
    3)静态代码块可以有多个,多个静态代码块之间是从上向下依次执行
    4)静态代码块 : 不能调用实例变量和非静态方法
    5)对Java类进行初始化
    3.2 非静态代码块
    1)非静态代码块是随着对象的创建而加载的
    2)非静态代码块的执行优先于构造器
    3)非静态代码块可以有多个,多个非静态代码块之间是从上向下依次执行
    4)非静态代码块 : 可以调用静态方法和类变量
    5)对Java对象进行初始化
  4. 思考 :什么时候使用代码块?
    静态代码块:随着类加载而执行的代码放在静态代码块中。
    非静态代码块:只要创建对象时就会执行的代码放在非静态代码块中。

接口

  1. 使用interface定义,格式:
权限修饰符(public/缺省的)interface  接口名{
 		}
  1. 说明:
    1)接口和类是并列存在的关系。
    2)接口中不能定义构造器的!意味着接口不可以实例化
    3)接口中只能有常量和抽象方法(JDK1.8之前)
    4)接口和接口之间是继承关系而且是多继承。 接口1 extends 接口2,接口3…
    5)类和接口的关系是实现关系而且是多实现。 类 implments 接口1 ,接口2…
    6)类实现接口后必须重写接口中的所有抽象方法,如果不想重写那么该类可以变成抽象类
    7)接口和类之间的多态性

  2. 接口在jdk1.8之后(包括1.8)中的新特性:
    接口中可以有 : 常量,抽象方法,静态方法,默认方法

  3. 说明:
    1)如何调用接口中的静态方法:接口名.静态方法名
    2)如何调用接口中的默认方法 :实现类的对象.默认方法名
    3)类优先原则 :一个类继承的父类和实现的接口(默认方法)中有同名同参的方法,那么调用的是父类中的。
    4)接口冲突 : 一个类实现多个接口,多个接口(默认方法)中有同名同参的方法,这时就会发生接口冲突。
    5)解决接口冲突 : 实现类只需要去重写该方法即可。再通过该类的对象调用此方法时调用的是重写的方法。
    6)实现类重写接口中的默认方法后调用接口中的默认方法:接口名.super.默认方法名

  4. 注意 : 如果使用抽象类和接口都可以的情况下,使用接口。

内部类

  1. 内部类 : 在一个类A的内部再定义一个类B,类A叫作外部类,类B叫作内部类
    内部类 : 成员内部类(静态(成员)内部类、非静态(成员)内部类)和局部内部类(方法内、代码块内、构造器内)
    1.1 作为类:
    1)可以继承父类,实现接口
    2)类内部可以有类的成员(普通类可以做的事情内部类都可以)。
    1.2 作为类的成员:
    1)可以被static修饰
    2)可以使用四种权限修饰符
    3)内部类还可以调用外部类的成员(属性,方法)
  2. 关注如下的2个问题
    2.1 如何创建内部类的对象?
    静态内部类:new 外部类名.内部类名()
    非静态内部类 :外部类的对象.new 内部类名()
//创建Dog实例(静态的成员内部类):
Person.Dog dog = new Person.Dog();
dog.show();
//创建Bird实例(非静态的成员内部类):
//Person.Bird bird = new Person.Bird();//错误的
Person p = new Person();
Person.Bird bird = p.new Bird();
bird.sing();

2.2 内部类如何调用外部类的成员(属性和方法)?
静态内部类 :外部类名.类变量名.静态方法 (只能调用外部类的类变量和静态方法)
非静态内部类 : 外部类名.this.属性名、方法名

//调用外部类的类变量和静态方法
Person.Dog.show();
//调用非静态内部类的方法和变量
Person.this.show();
  1. 匿名内部类的特点
    1)匿名内部类必须继承父类或实现接口
    2)匿名内部类只能有一个对象
    3)匿名内部类对象只能使用多态形式引用

异常

概述
Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如:StackOverflowError和OOM。一般不编写针对性的代码进行处理。

Throwable

  1. Error : 发生Error是没有针对性的代码进行处理的

  2. Exception: 发生Exception后有针对性的代码进行处理

  3. 编译时异常:程序在编译时发生的异常(javac 源文件名.java)
    编译时异常必须处理,否则程序不能执行。
    比如:FileNotFoundException : 文件找不到异常

  4. 运行时异常:程序在运行时发生的异常(java 字节码文件名)
    比如:NullPointerException : 空指针异常
    ArrayIndexOutOfBounds : 数组下角标越界
    ClassCastException:两个类型间转换不兼容时引发的运行时异常
    NumberFormatException:数字格式异常查类中对应是否正确
    InputMismatchException:输入类型不匹配异常
    ArithmeticException:算术运算异常

抓抛模型

  1. 抛 (发生异常): 当程序在正常的执行过程中,如果一旦执行到某行代码时发生异常。那么系统(JVM)将会根据异常的类型创建对应的异常类型的对象并抛出,抛出给代码的执行者。同时终止程序的运行。
    ①系统向外抛 ②手动向外抛
  2. 抓(处理异常):
    第一种 : try-catch-finally
    第二种 : throws

处理异常方式一:try-catch-finally

  1. 格式:
try{
		可能会发生异常的代码;
	}catch(异常类型1 变量名){
		处理异常1的代码;
	}catch(异常类型2 变量名){
		处理异常2的代码;
	}
	......
	finally{
		一定会执行的代码;
	}
	
  1. 说明:
    1)在执行try中的代码时一旦发生异常,系统会根据对应的异常类型创建对象并抛出。然后会根据catch后面的异常类型进行匹配,一旦匹配成功则执行相应的代码。执行完毕后如果有finally那么继续执行finally中的代码,然后跳出try-catch结构继续向下执行。如果没有和catch后面的异常类型匹配成功,终止程序的执行。如果有finally继续执行finally中的代码。
    2)finally可以省略,finally中的代码一定会执行。
    3)catch可以有多个,catch后面的异常类型如果存在子父类关系那么子类在上父类在下。如果不存在子父类关系那么谁上谁下都可以
    4)可以有的结构方式 : try-finally try-catch try-catch-finally
    5)处理异常的方式 :
    getMessage() - 异常信息 (使用自定义异常时用的比较多)
    printStackTrace() - 异常的详细信息
  2. finally的再说明:
    1)就算在try和catch中执行了return那么finally中的代码也一定会执行。
    2)就算catch中再次发生异常,finally也一定会执行

处理异常方式二 :throws + 异常类型

  1. 格式 : throws 异常类型1,异常类型2…
    throws : 本身没有真正的处理掉异常,而是把异常向上抛,抛给方法的调用者去处理。

  2. throws和try-catch-finally的区别?
    throws :本身没有真正的处理掉异常
    try-catch-finally :真正的处理掉了异常

  3. 什么时候使用try-catch-finally? 真正需要处理掉异常的时候

  4. 什么时候不能使用throws?
    ①父类被重写的方法没有throws子类重写的方法也不能throws。
    ②子类被重写方法抛出的异常不大于父类被重写方法抛出的异常

  5. 什么时候必须使用throws?
    当我们需要调用多个方法进行数据的传递,如果是因为数据的原因造成的异常,那么中间任何方法都不能去处理。只能由方法的调用者(写数据的那人)进行处理。

  6. 注意
    1)父类被重写的方法没有throws子类重写的方法也不能throws
    2)子类被重写方法抛出的异常不大于父类被重写方法抛出的异常

  7. throw(制造异常):手动向外抛异常
    格式 :throw new 异常类的对象;
    如果throw了一个抛编译时异常 - 该异常必须得处理我们都是throws

自定义异常

  1. 自定义一个类并继承Exception(编译时异常)或者RuntimeException(运行时异常)
  2. 提供两个构造器一个空参一个有参(调用父类的有参构造器)
  3. 提供一个serialVersionUID,也可以不写系统默认会添加一个,但是建议显示提供一个
public class MyException extends RuntimeException{
	/**
	 * serialVersionUID也可以不写系统默认会添加一个,但是建议显示提供一个
	 */
	private static final long serialVersionUID = -7736287090372348682L
	public MyException(){	
	}
	public MyException(String message){
		super(message);
	}
} 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值