Java基础--类和类之间的基本关系

简述:
类(Class)实际上是对某种类型的对象定义变量和方法的原型。它表示对现实生活中一类具有共同特征的事物的抽象,是面向对象编程的基础。
它为同一类的事物提供一个模板,比如人这个类就可定义人的基本特征,如状态量男、女;数值量身高、体重等;动作量走、跑、跳等,对于每个人来说就是人这个类的一个实体,是这个类的具体化,人和人之间的差距可以通过以上定义的量之间的不同来体现。

第一讲>>>>继承

注意:千万不要随便用继承,为了获取其他类的功能简化代码而继承,必须是累与类之间有所属关系才可以继承.所属关系 is a.
Java语言中:java语言只支持单继承,不支持多继承.(并非多重继承).由于多继承容易带来安全的隐患.当多个父类中定义了多个相同的内容但内容不同时,要执行哪一个不确定!
java虽然不支持多继承,但是java用了另一种体现方式来完成,叫做多实现.(借口).java支持多重继承,也就是一个继承体系.
那么如何使用一个继承体系中的功能呢?想要使用体系,先查阅体系中父类的描述,因为父类中定义的是该体系中共性的功能,通过了解共性功能,就可以知道该体系的基本功能.那么这个体系这时候已经基本可以使用了.在具体调用时,要创建最子类的对象,因为

1. 有可能父类不能创建对象.
2. 创建自类对象是用更多的功能,包括基本的也包括特有的.

简单一句话,查阅父类功能,创建子类对象使用功能.
子父类出现后,类成员的特点:
类中成员:1.变量.2.函数.3.构造函数.
如果子类中出现非私有同名成员变量时,子类要访问同类中的变量,用this,父类则用super.super是用方法同this.
子类中同名于父类函数的特点:重写(覆盖)(非重载).
记住:
重载:只看同名函数的参数列表类型个数.
重写:子父类方法要一模一样.(参数类型个数必须相同!)
用子类继承父类,沿袭了父类的功能,到子类中,但是子类虽然具备该功能,但是功能却跟父类不一致,这时没有必要定义新功能.而是使用覆盖原父类中的函数.,保留父类中功能的定义,并重写功能内容.
覆盖:子类覆盖父类,必须保证子类权限大于等于父类,才可以覆盖,否则编译失败.
静态只能覆盖静态.

子父类中的构造函数
构造函数随着类名走,类名不能相同.因此子类构造函数不能继承父类构造函数.但是创建子类对象时会调用父类的构造函数(在子类的构造函数第一行有隐式的super()父类构造函数).
为什么子类一定要访问父类中的构造函数:
子类创建时,父类中的数据子类可以直接获取,所以在子对象建立时,需要先看看父类是否对这些数据进行初始化,如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定.
注意:super语句一定定义在子类构造函数的第一行.
子类的实例化过程
结论:
子类的所有的构造函数默认都会访问父类的空参的构造函数,因为每一个子类构造函数内第一行都有一句隐式的super();
当父类中没有空参数的构造函数时,子类必须手动通过super或者this形式访问指定的父类中的构造函数.当然,子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数.子类中至少有一个构造函数会访问父类中的构造函数.

Final
Final:最终,作为一个修饰符.

* 可以修饰类,变量,函数.
* 被final修饰的类不能被继承.为了避免被继承,被子类复写功能.
* 被final修饰的方法不可以被复写(重写).
* 被final修饰的变量是一个常量只能被复制一次,既可以修饰成员变量,也可以修饰局部变量.
* 内部类定义在类中的局部位置上是,只能fangwen该局部final修饰的局部变量.当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字,方便于阅读.而这个值不需要改变,所以加个final修饰不允许改变.作常量是用.常量的书写规范所有的字母都大写,如果多个单词组成,则单词间通过"_"连接.
* 内部定义类在类中的局部位置上时,只能访问该局部被final修饰的局部变量.

抽象类
当多个类中定义相同的功能,但是功能主题不同,这时可以进行向上抽取,只抽取功能定义,而不抽取功能主体.
抽象类的特点:

1. 抽象方法必须存在于抽象类中.
2. 抽象方法和抽象类都必须被abstract关键字修饰.
3. 抽象类不可以用new问问创建对象,因为调用抽象方法没有意义.
4. 抽象类的方法要被使用,必须由子类复写所有抽象方法,建立子类对象调用.如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类.
5. 抽象类比一般类多了抽象方法.可以在类中定义抽象方法,在抽象类中可以定义非抽象方法.此时可防止创建该类的对象.不可以实例化.

抽象类和一般类没有太大区别,描述事物的方式也一样.不过对于事物中不确定的部分,需要通过重载明确出现,因此不定义主体.

abstract class Employee{
	private String name;
	private String id;
	private double pay;
	public Employee(String name, String id, double pay) {
		super();
		this.name = name;
		this.id = id;
		this.pay = pay;
	}
	public abstract void work();
	//由于不同的雇员,所做的工作不同,因此这个方法定义为抽象方法.
	//方便不同员工种类从这个雇员类继承,有了几个成员变量的同时,也可以实现各自的工作方式.

}

另一方面,我们讲一下模板方法设计模式:

class GetTime{
	public void getTime(){
		long start = System.currentTimeMillis();
		
		for (int i = 0; i < 100; i++) {
			System.out.println("code run");
		}//粗略计算这段代码所运行的时间
		
		long end = System.currentTimeMillis();
		
	}
}
class TemplateDemo{
	public static void main(String[] args) {
		GetTime gt = new GetTime();
		gt.getTime();
	}
}

所需要计算运行时间的代码可以封装到一个方法中,这样方便与于我们对程序进行扩展.代码如下:

class GetTime{
	public void getTime(){
		long start = System.currentTimeMillis();
		
		runcode();
		
		long end = System.currentTimeMillis();
		
	}

	private void runcode() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 100; i++) {
			System.out.println("code run");//封装了所需要计算运行时间的代码,程序看起来更加明了,想要计算新的代码的运行时间只需更新这段代码即可!
		}
	}
}

现在,可以继承该类,复写runcode,即可获取代码运行时间!
此时将getTime()命名为final类即可避免子类复写getTime()函数.
这类设计方式成为
模版方法设计模式.提高了扩展性和复用性!
什么是模板方法呢?在定义功能时,功能的一部分是确定的,但是有一部分是不确定的,而确定的部分在使用不确定的部分,那么这时就将不确定的部分暴漏出去,由该类的子类去完成这个功能.

第二讲>>>接口
初期理解可以认为是一特殊的抽象类,当抽象类的方法都是抽象的,那么该类可以通过接口的形式来表示.
接口定义时,格式特点:

1. 接口中常见定义:常量,抽象方法.
2. 接口中的成员都有固定修饰符.
	1. 常量:public static final
	2. 方法:public abstract

实现,代码中的关键字为implements.例如class subInter implements Interface
由于有抽象方法,接口不可以创建对象需要被子类实现,子类对接口的抽象方法全部都覆盖后,子类才可以实例化.否则子类是一个抽象类.

接口可以被类多实现.(一个类可以同时实现多个接口).也是对不支持多继承的弥补.

1. 类与类之间继承关系.
2. 类与接口是实现关系.
3. 接口与接口之间是继承关系.

//A B两接口中有两个变量类型不同,函数名相同的方法,这样C继承了A B,是不允许的.
//当父类中有一些功能子类不需要的时候,可以把那些不需要的功能另外定义一个接口.即:基本功能定义在父类中,扩展功能定义在接口中.

interface A{
	void methodA();
	int show();
}
interface B{
	void methodB();
	boolean show();
}
interface C extends B,A{
	void methodC();
}
class D implements C{
	public void methodA(){}
	public void methodC(){}
	public void methodB(){}
	public int show(){}
	public boolean show(){}
}

第三讲>>>多态
可以理解为事物存在的多种体现形态.
人 <--------------男人-------------- 女人
或者说
动物<------------猫----------------狗
建立对象时我们可以:
猫 X = new 猫();
动物 x = new 猫();

1. 多态的提现
	1. 父类的引用指向了自己子类的对象.
	2. 父类的引用也可以接受自己的子类对象.

2. 多态的前提
	1. 必须是类与类之间的关系,要么继承,要么实现.
	2. 通常还有一个前提,存在覆盖.

3. 多态的优点

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

1. 多态的弊端

提高了扩展性,但是只能是用父类的引用访问父类的成员.
4. 多态的应用

package test1;

public class DuotaiDemo {
		public static void main(String[] args) {
//			fun(new Cat());
			Animal an = new Cat();
			Cat c = (Cat)an;//向下转型
			c.mouse();
			DoS d1 = new DoS();
			d1.fun(new Cat());
		}
		
}
class DoS
{
	public static void fun(Animal a) //向上转型
	{
		a.eat();
		if(a instanceof Cat)
		{
			Cat c = (Cat)a;
			c.eat();
		}
		else if(a instanceof Dog)
		{
			Dog d = (Dog)a;
			d.eat();
		}
	}
}

interface Animal
{
	void eat();
	void mouse();
}
class Cat implements Animal
{
	public void eat()
	{
		System.out.println("fish");
	}
	public void mouse()
	{
		System.out.println("Mouse");
	}
}
class Dog implements Animal
{
	public void eat()
	{
		System.out.println("bone");
	}
	public void mouse()
	{
		System.out.println("NONONO");
	}
}

那么在多态的使用中,我们会遇到这样的问题:创建一个对象的时候,方法是属于左边,还是右边呢?
在多态中成员函数的特点:
重点:在编译时期,参阅引用型变量所属的类中是否有调用的方法.如果有,编译通过,如果没有编译失败.

* 在运行时期:参阅对象所属的类中是否有调用的方法.
* 简单总结下就是:成员函数在多态调用的时候,编译看左边,运行看右边.
* 在多态中,成员变量的特点:无论编译和运行,都参考左边(引用型变量所属类).
* 在多态中,静态成员函数的特点:编译,运行的时候都参考左边.

多态的主板示例:
电脑运行实例:
电脑运行基于主板.

package test1;

public class DuotaiDemo3 {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Mainboard mb = new Mainboard();
		mb.run();
		mb.usePCI(new Cpu());
	}
}
interface PCI
{
	void open();
	void close();
}
class Mainboard
{
	public void run()
	{
		System.out.println("zhuban run");
	}
	public void usePCI(PCI p)
	{
		if(p!=null)
		{
			p.open();
			p.close();
		}
	}
}
class Cpu implements PCI
{
	public void open()
	{
		System.out.println("Cpu run");
	}
	public void close()
	{
		System.out.println("Cpu boom");
	}
}

想上网,得在主板这个类里面增加功能.
接口型引用指向自己的子类对象.这样非常方便以后的扩展.

多态的扩展实例:
需求:数据库的操作

  1. 链接数据库
  2. 操作数据库 :::添加数据,删除数据,更改数据,查询数据.
  3. 关闭数据库链接.
package test1;

public class DuotaiDemo4 {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		uiop u = new uioh();
	}

}

interface uiop
{
	public void add(User u);
	public void delete(User u);
}

class uioj implements uiop
{
	public void add(User u)
	{
		
	}
	public void delete(User u)
	{
		
	}
}

class uioh implements uiop
{
	public void add(User u)
	{
		
	}
	public void delete(User u)
	{
		
	}
}
class User
{
	
}

第四讲>>>内部类,匿名内部类

内部类的访问规则:

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

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

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

package test1;

public class InnerClassDemo {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Outer o = new Outer();
		o.method();
//		Outer.Inner oi = new Outer().new Inner();
		//建立内部类对象的时候的固定格式
		new Outer.Inner().func();//当内部类为静态的时候,调用格式
	}
}
class Outer
{
	int x = 3;
	static class Inner //inner class 可以被private,static修饰
	{
		int x = 5;
		void func() //static时,则内部类必须是static的
		{//当外部类中的静态方法访问内部类的时候,内部类也必须是静态的.
			int x = 6;
			System.out.println("inner class:"+x);
		}// Inner.this.x 5  Outer.this.x 3   x 6
	}
	void method()
	{
//		Inner in = new Inner();
//		in.func();
	}
}

访问格式:
当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中.
可以直接建立内部类对象.格式为:外部类名.内部类名对象名 = 外部类对象.内部类对象(new外部类().new内部类()).
当内部类在成员位置上,就可被成员修饰符修饰,比如private,将内部类在外部类中进行封装.
Static:内部类就具备了静态的特性,可以直接被外部类对象调用.
当内部类被static修饰后,只能直接访问外部类中的静态成员,出现了访问限制.
在其他外部类中,如何直接访问内部类中的非静态成员呢?
New Outer.Inner().function();
在其他外部类中,如何直接访问内部类中的静态成员呢?
Outer.Inner.function();
注:当内部类中定义了静态成员,该内部类必须是静态的!
当外部类中的静态方法访问内部类时,内部类必须是static的.
当描述事物时,事物的内部还有事物,该事物用内部类来描述.因为内部事物在使用外部事物的内容.
局部内部类不能定义静态成员,也不能用private修饰.
内部类定义在局部时,不可以被成员修饰符修饰,可以直接访问外部类中的成员,因为还持有外部类中的引用,但是不可以访问它所在的局部中的变量,只能访问被final所修饰的局部变量.

匿名内部类
匿名内部类,就是内部类的简写格式.
定义匿名内部类的前提:
内部类必须是继承一个类(这个类须是外部类)或者实现接口.

匿名内部类的格式:
new 父类或者接口()
{
定义子类的内容
}
例如new Object() { void func() { System.out.println("aa"); } }.func();; }
其实匿名内部类就是一个匿名子类对象 ,而且这个对象有点胖,可以理解为带内容的对象.
但是每次调用匿名对象完了以后,想要再次使用匿名类的功能,就需要重新建立一个对象.
当匿名内部类继承的类,是抽象类且抽象方法很多,非常麻烦.
内部类有时候是方便的,注意使用会方便我们写代码.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值