黑马程序员_面向对象02

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------

面向对象

继承:

1,提高了代码的复用性

2,让类与类之间产生了关系,有了这个关系,才有了多态的特性

注意:

千万不要为了获取其他类的功能,简化代码而继承

必须是类与类之间有所属关系才可以继承。

 

java中只支持单继承,不支持多继承

因为多继承容易带来安全隐患:当多个父类中定义了相同的功能

当内容不同时,子类对象不确定要运行哪一个。

但是java保留这种机制,并用另一种体现形式来完成表示。多实现

java支持多层继承

 

如何使用一个继承体系中的功能呢?

要使用体系,先查阅父类描述,因为父类中定义的是体系中的共性内容。

通过了解共性功能,就可以知道该体系的基本功能

那么这个体系已经可以基本使用了。

在具体调用时,要创建最子类的对象

1,因为有可能父类不能创建对象

2,创建子类对象能使用更多的功能,包括基本的也包括特有的

简单一句话:查阅父类功能,创建子类对象使用功能。

 

继承体系的性质:

1,变量

如果子类中出现非私有的成员变量时

子类要访问本类中的变量用this,要访问父类的变量用super

this代表的是本类对象的引用

super代表的是父类对象的引用

 

2,子父类中的函数

当子类出现和父类一模一样的函数时

当子类对象调用该函数,会运行子类函数的内容

如同父类的函数被覆盖一样

 

这种情况是函数的另一特性:重写(覆盖)

 

当子类继承父类,沿袭了父类的功能,到子类中

子类虽具备该功能,该功能的内容却和父类不一致

这时没有必要定义新功能,保留父类的功能定义,并重写功能内容

 

覆盖:

1,子类覆盖父类必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败

2,静态只能覆盖静态。

 

记住:

重载:只看重名函数的参数列表

重写:子父类方法要一模一样。

 

3,子父类中的构造函数

 

在对子类对象进行初始化时,父类的构造函数也会运行

那是子类的构造函数默认第一行有一条隐式的语句super();

super()会访问父类中空参数的构造函数,而且子类中所以构造函数默认第一行都是super();

 

为什么子类一定要访问父类中的构造函数?

因为父类中的数据子类可以直接获取,所以子类建立对象时,需要先查看父类是如何对这些数据进行初始化的

所以子类在对象初始化时要先访问一下父类中的构造函数

如果要访问父类中指定的构造函数,可以通过手动定义super语句来指定

 

注意:super语句一定定义在子类构造函数的第一行

 

 

子类的实例化过程

结论:

1 子类的所有构造函数,默认都会访问父类中空参数的构造函数

因为子类每一个构造函数内的第一行都有一句隐式的super()

 

2 当父类中没有空参数的构造函数时,子类必须通过superthis语句来指定要访问的构造函数

3 当然子类构造函数的第一行也可以手动指定this语句来访问本类中的构造函数

子类中至少有一个构造函数会访问父类中的构造函数

代码演示1:

class Father
{	
	Father()
	{
		System.out.println("Father Run");
	}
	Father(int x)
	{
		System.out.println("Father....."+x);
	}
	int num=4;
	void show()
	{
		System.out.println("show Father");
	}
	void speak()
	{
		System.out.println("vb");
	}
}

//子类继承父类
class Son extends Father
{	
	//子类构造函数,第一行默认有一个空参数的super()
	Son()
	{
		//super();
		//super(4);
		System.out.println("Son run");
	}
	//带参数的构造函数
	Son(int x)
	{
		System.out.println("Son..."+x);
	}
	//int num=5;
	//覆盖show方法
	void show()
	{
		System.out.println("show Son");
	}
	//覆盖speak方法
	void speak()
	{
		System.out.println("java");
	}
}

class ExtendsDemo2
{
	public static void main(String[] args)
	{
		Son s = new Son();
		Son s1 = new Son(4);
		s.show();
		s.speak();
		//System.out.println(s.num+"...."+s.num);
	}
}

final:最终。作为一个修饰符

1,可以修饰类、变量、函数

2,被final修饰的类不可以继承。为了避免被继承,被子类复写功能

3,被final修饰的方法不能被复写

4,被final修饰的变量是一个常量,只能被赋值一次,既可以修饰成员变量,又可以修饰局部变量

      当在描述事物时,一些事物的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字,方便阅读

      而这个值不需要改变,加上final修饰。作为常量:所有的字母都大写,如果由多个单词组成,单词间通过下划线_连接

5,内部类定义在类中局部位置上时,只能访问局部被final修饰的局部变量

代码演示2:

class Demo
{
	final int x=3;
	public static final double PI=3.14;
	final void show1()
	{}
	void show2()
	{
		final int y = 4;
		System;out.println(3.14);
	}
}


 

抽象类:

当多个类中出现相同功能,但是功能主题不同

这时可以进行向上抽取,这时只抽取功能定义,不抽取功能主体

 

抽象类的特点:

1,抽象方法一定在抽象类中

2,抽象方法和抽象类abstract关键字修饰

3,抽象类不可以用new创建对象,因为调用抽象方法没意义

4,抽象类中的抽象方法要被使用必须由子类复写其抽象方法后,建立子类对象调用

5,如果子类只覆盖了部分抽象方法,该子类还是一个抽象类

 

抽象类和一般类没有太大的区别。

该如何描述事物,就如何描述事物,只不过该事物中出现了一些看不懂的东西。

这些不确定的部分,也是该事物的功能,需要明确出现。但是无法定义主体

 

抽象类比一般类多了抽象方法

抽象类不可以实例化

 

特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象

代码演示3:

//定义一个抽象类
abstratc class Student
{
	//定义一个抽象方法
	abstract void study();
}

//定义一个子类继承抽象类
class BaseStudent extends Student
{
	//覆盖study()方法
	void study()
	{
		System.out.println("Base Student");
	}
}

class AdvStudent extends Student
{
	//覆盖父类的方法,实现自己的方法体
	void study()
	{
		System.out.println("Adv Student");
	}
}

class AbstractDemo
{
	public static void main(String[] args)
	{
		new Student();
		//new BaseStudent().study();
	}
}


 

接口:

初期理解,可以认为是一个特殊的抽象类

当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示

 

class用于定义类

Interface用于定义接口

 

接口定义时,格式特点:

1,接口中常见定义:常量,抽象方法

2,接口中的成员都有固定修饰符

       常量public static final

       方法public abstract

 

接口是不能创建对象的,因为有抽象方法。

需要被子类实现,子类对抽象接口中的方法全部覆盖后,子类才可以实例化

否则子类是一个抽象类

 

接口可以被类多实现,也是对多继承不支持的转换形式。java支持多实现。

代码演示4:

 

interface Inter
{
	//定义常量NUM
	public static final int NUM=3;
	//定义抽象方法
	public abstract void show();
}

interface InterA
{
	public abstract void methord();
}

//定义类实现Inter接口
class Test implements Inter
{
	//覆盖show方法
	public  void show() {}
}

class demo
{
	public void Fuction() {}
}

interface A
{
	public abstract void methordA();
}

interface B // extends A
{
	public abstract void methordB();
}

//接口可以继承多个接口
interface C extends A,B
{
	public abstract void methordC();
}

//D类实现了C接口,必须覆盖3个方法
class D implements C
{
	public void methordA() {}
	public void methordB() {}
	public void methordC() {}
}
class InterfaceDemo
{
	public static void main(String[] args)
	{
		Test t = new Test();
		System.out.println(t.NUM);
		System.out.println(Test.NUM);
		System.out.println(Inter.NUM);
	}
}

模板方法模式:

需求:获取一段程序运行的时间

原理:获取程序开始和结束的的时间,并相减

获取时间:System.currentTimeMillis();

 

当代码完成优化后,就可以解决这类问题

这种方式:模板方法设计模式

 

什么是模板方法呢?

在定义功能时,功能的一部分是确定的,但是有一部分不确定

那么这时就将不确定的部分暴露出去。由该类的子类去完成

代码演示5:

abstract class GetTime
{
	public final void getTime()
	{
		long start = System.currentTimeMillis();//方法运行前的时间
		runcode();	//不确定的方法
		long end = System.currentTimeMillis();	//方法运行后的时间
		System.out.println("毫秒 :"+(start+end));
	}
	public abstract void runcode();
}

class SubGetTime extends GetTime
{
	//子类实现runCode方法
	public void runcode()
	{
		for(int x=0; x<400; x++)
		{
			System.out.print(x);
		}
	}
}

class TemplateDemo
{
	public static void main(String[] args)
	{
		//创建子类对象
		SubGetTime gt =new SubGetTime();
		//调用父类的方法
		gt.getTime();
	}
}

 

多态:

可以理解为事物存在的多种体现形态

1,多态的体现

       父类引用指向了自己的子类对象

       父类引用可以接受自己的子类对象

2,多态的前提

       必须是类与类之间有关系,要么继承,要么实现

       通常还有一个前提,存在覆盖

3多态的好处

       多态的出现大大的提高了程序的拓展性

4,多态的弊端

       提高了拓展性,但只能使用父类的引用访问父类中的成员

5,多态的应用

 代码演示6:

//定义一个抽象的父类
abstract class Animal
{
	//共性方法
	public abstract void eat();
}

class Cat extends Animal
{
	//子类实现自己的eat方法
	public void eat()
	{
		System.out.println("eat fish");
	}
	//子类独有的catchMouse方法
	public void catchMouse()
	{
		System.out.println("catch mouse");
	}
}

class Dog extends Animal
{
	//子类实现自己的eat方法
	public void eat()
	{
		System.out.println("eat bone");
	}
	//子类独有的lookafter方法
	public void lookafter()
	{
		System.out.println(" look after ");
	}
}

class Pig extends Animal
{
	//子类实现自己的eat方法
	public void eat()
	{
		System.out.println("siliao");
	}
	//子类独有的方法
	public void gongdi()
	{
		System.out.println("gongdi");
	}
}

class DuoTaiDemo
{
	public static void main(String[] args)
	{
		//Cat c= new Cat();
		//c.eat();
		//c.catchmouse();
		//fuction(new Dog());
		//fuction(new Pig());



		Animal a = new Dog();			
		//类型提升。(向上转型)
		a.eat();
		//如果想要调用猫中的特有方法时,如何操作
		//强制将父类的引用,转成子类类型(向下转型)
		if (a instanceof Cat)
		{
			Cat c= (Cat)a;
			c.catchMouse();
		}
		else if(a instanceof Dog)
		{
			Dog c=(Dog)a;
			c.lookafter();
		}
		//千万不要出现这样的操作,将父类对象转换成子类类型
		//我们能转换的是父类引用指向自己的子类对象时,该引用可以被提升,也可以被强制转换
		//多态自始至终都是子类对象在做着变化


		//c.eat();
		//fuction(new Cat());
		//fuction(new Dog());
		//fuction(new Pig());
	}
	/*
	public static void  fuction(Cat c)
	{
		c.eat();
	}
	
	public static void fuction(Dog d)
	{
		d.eat();
	}
	*/
	public static void fuction(Animal a)
	{
		a.eat();
	}
}


 

在多态中成员函数的特点:

在编译时期,参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过;如果没有,编译失败

在运行时期,参阅对象所属的类中是否有调用的方法

简单总结就是:成员函数在多态调用时,编译看左边,运行看右边

多态中成员变量的特点:

无论编译和运行,都参考左边

在多态中,静态成员函数的特点:

无论编译和运行,都参考左边

代码演示7:

class Father
{	
	//int num =5;
	void method1()
	{
		System.out.println("Father method_1");
	}
	void method2()
	{
		System.out.println("Father method_2");
	}
}

class Son extends Father
{	
	//int num =8;
	void method1()
	{
		System.out.println("Son method_1");
	}
	void method3()
	{
		System.out.println("Son method_3");
	}
}


class DuoTaiDemo2
{
	public static void main(String[] args)
	{
		Father f = new Son();	//父类引用指向子类对象
		f.method1();	//编译时看父类中有无method1(),运行时看子类Son中有无定义method1()
		f.method2(); 
		f.method3();	//编译失败
	}
}

 

Object

是所有对象的直接或间接父类

该类中定义的是所有对象都具备的功能

异常:

就是程序在运行时出现不正常情况

1,异常的由来:

问题也是现实生活中的具体事物,也可以通过java的类的形式进行描述。并封装成对象

其实就是java对不正常情况进行描述后的对象体现

 

对于问题的划分:两种:一种是严重的问题,一种是非严重的问题

对于严重的java通过Error类进行描述

              对于Error一般不编写针对性的代码对其进行处理

对于非严重的java通过Exception类进行描述。

              对于Exception可以使用针对性的处理方式进行处理

无论Error或者Exception都有一些共性内容

比如:不正常的信息,引发原因等

 

Thowable

       |--Error

       |--Exception

 

2,异常的处理:

java提供了特有的语句进行处理

try

{

       需要被检测的代码;

}

 

catch(异常类变量)

{

       处理异常的代码;

}

 

finally

{

       一定会执行的语句;

}

 

3,对捕获到的异常进行常见方法操作

       String getMessage();  获取异常的信息

 

在函数上声明异常

便于提高安全性,让调出进行处理。不处理编译失败

 

对多异常的处理

1,声明异常时,建议声明更具体的异常。这样处理可以更具体

2,对方声明几个异常,就对应几个catch块。不要定义多余的catch

       如果多个catch中的异常出现继承关系,父类异常catch块放在最下边

 

建议在进行catch处理时,catch中一定要具体的处理方式

不要简单的定义一句 e.printStackTrace();

也不要简单的就写一条输出语句

代码演示8:

class Demo
{
	int div ( int a ,int b) throws ArithmeticException , ArrayIndexOutOfBoundsException	
	//在功能上通过static关键字声明了该功能有可能出现问题
	{
		int arr [] = new int [a];
		System.out.println(arr[4]); 
		return a/b;
	}
}
	
class ExceptionDemo
{
	public static void main(String[] args)
	{
		Demo d = new Demo();
		try
		{
			int x = d.div(4,0);
			System.out.println("x=="+x);
		}
		catch(ArithmeticException e)		//Exception e = new ArithmeticException();
		{
			System.out.println("除零");
			System.out.println(e.getMessage());	
			System.out.println(e.toString());
			e.printStackTrace();
				//其实jvm默认的异常处理机制,就是在调用printStackTrace方法。打印异常在堆栈的跟踪信息			
		}
		catch (ArrayIndexOutOfBoundsException e)
		{
			System.out.println(e.getMessags());
			System.out.println("下标越界");
		}
	
		System.out.println("over");
	}
}


 

因为项目中会出现特有的问题

而这些问题并未被java所描述并封装对象

所以对于这些特有的问题可以按照java的对问题封装的思想

将特有的问题进行自定义的异常封装

 

自定义异常

 

需求:在本程序中除数为负数,也视为错误,无法进行运算

那么就需要对这个问题进行自定义的描述

 

当在函数内部出现throw抛出异常对象,那么就必须要给对应的处理动作

要么在内部try catch 处理,要么在函数上声明让调用者处理

 

一般情况下,函数类出现异常,函数上需要声明

 

发现打印的结果中只有异常的名称,却没有异常的信息

因为自定义的异常并未定义信息

 

如何定义异常信息呢?

 

因为父类已经把异常信息的操作都完成了

所以子类只要在构造时,将异常信息传递给父类通过super语句

就可以通过getMessage方法获取自定义的异常信息

 

自定义异常:

必须是自定义类继承Exception

 

继承Exception的原因:

异常体系有一个特点:因为异常类和异常对象都需要被抛出

他们都具备可抛性。这个可抛性是Throwable体系中独有的特点

 

只有这个体系中类和对象才可以被throwsthrow多操作

 

throwthrows的区别

throws使用在函数上

throw使用在函数内

 

throws后跟异常类;可跟多个;用逗号隔开

throw后跟的是异常对象

代码演示9:

class FuShuException extends Exception
{
	private String msg;
	FuShuException( String msg)
	{
		this.msg=msg;
	}
	public String getMessage()
	{
		return msg;
	}
}

class Demo
{
	int div( int a , int b ) throws FuShuException
	{
		if (b<0)
			throw new FuShuException("出现了除数是负数的情况");
		return a/b;
	}
}

class ExceptionDemo2
{
	public static void main(String[] args)
	{
		Demo d = new Demo();
		try
		{
			int x = d.div( 4,-1);
			System.out.println("x= "+x);
		}
		catch( FuShuException e)
		{
			System.out.println( e.toString());
			System.out.println("除数为负数了");	
		}
		
		System.out.println("over ");
	}
}

 

RuntimeException

Exception中有一个特殊的子类异常,RuntimeException

如果在函数内容抛出该异常,函数上可以不用声明,编译一样通过

如果在函数上声明了该异常;调用者可以不用进行处理

 

之所以不用在函数上声明,是因为不需要调用者处理

当该异常发生,希望程序停止。因为在运行时,出现了无法继续运算的情况

希望停止程序后,对代码进行修正

 

自定义异常时:如果该异常的发生,无法再继续进行运算

就让自定义异常类继承RuntimeException

 

对于异常分两种:

1,编译时被检测的异常

2,编译时不被检测的异常(运行时异常。RuntimeException及其子类

代码演示10:

Demo
{
	int div ( int a ,int b)
	{
		if(b==0) 
			throw new ArithmeticException("被零除");
		return a/b;
	}
}

ExceptionDemo3
{
	public static void main(String[] args)
	{
		Demo d = new Demo();
		int x = d.div(4,1);
		System.out.println("x= "+x);
	}
}


 

内部类:

内部类的访问规则:

1,内部类可以直接访问外部类中的成员,包括私有,之所以可以直接访问内部类中的成员,是因为内部类持有了一个外部类的引用。格式:外部类名.this

2,外部类要访问内部类,必须建立内部对象

 

访问格式:

1,当内部类定义在外部类的成员位置上,也非私有,可以在外部其他类中直接建立内部类对象

格式:

       外部类名.内部类名变量名 = 外部对象.内部对象

       Outer.Inner in = new Outer().new Inner();

2,当内部类在成员位置上,就可以被成员修饰符所修饰

       比如private:将内部类在外部类中进行封装

       static:内部类就具备了静态的特性

       当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问权限

      

       在外部其他类中,如何直接访问静态内部类的非静态成员呢?

       new Outer.Inner().functin();

       在外部其他类中,如何直接访问静态内部类的静态成员呢?

       Outer.Inner.function();

      

       注意当内部类定义了静态成员,该内部类必须是静态的

       当外部类中的静态方法访问内部类时,内部类也必须是static

 

当描述事物时,事物的内部还有事物,该事物用内部类描述

因为内部事物在使用外部事物的内容。

代码演示11:

class Outer
{
	private static int x;
	static class Inner
	{
		static void fuction()
		{	
			int x = 4;
			System.out.println("inner"+ x);
		}
	}
	static class Inner2
	{
		 void show()
		{
			System.out.println("show run");
		}
	}
	public static void method()
	{
		//Inner in = new Inner();
		//in.fuction();
		new Inner2().show();
	}
}

class InnerClassDemo
{
	public static void main(String[] args)
	{
		Outer out = new Outer();
		out.method();
		new Outer.Inner().fuction();
		//直接访问内部类的成员
		//Outer.Inner in =  new Outer().new Inner();
		//in.fuction();
	}
}


 

内部类定义在局部时

1,不可以被成员修饰符修饰

2,可以直接访问外部类中的成员,因为还持有外部类的引用,但是不可以访问它所在的局部的变量,只能访问被final修饰的局部变量

匿名内部类:

1,匿名内部类其实就是内部类的简写格式

2,定义匿名内部类的前提:

       内部类必须是继承一个类或实现接口

3,匿名内部类的格式:new 父类或者接口() {定义子类的内容}

4,其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象

5,匿名内部类中定义的方法最好不超过三个

代码演示12:

abstract class AbsDemo
{
	abstract void show();
}

class Outer
{
	int x = 3;
	/*
	class Inner extends AbsDemo
	{
		void show()
		{
			System.out.println("show :"+ x);
		}
		void abc()
		{
			System.out.println("abc :"+x);
		}
	}
	*/
	public void function()
	{
		//new Inner().show();
		new AbsDemo()
		{
			void show()
			{
				System.out.println("show :"+x);
			}
			void abc()
			{
				System.out.println("abc");
			}
		}.abc();
	}
}


 

 



 


1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值