《java开发实战经典》李兴华——C6. 面向对象(高级篇)——Part1

一、继承的基本概念

1.格式:

             class 父类{}

             class 子类 extends 父类{}

2.实现:

class Person{
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

class Student extends Person{
	private String school;

	public String getSchool() {
		return school;
	}

	public void setSchool(String school) {
		this.school = school;
	}
	
}

3.注意:

1)Java中一个子类只能有一个父类。

2)子类可以访问父类中的非私有方法,但不能直接调用父类中的私有成员(可通过getter/setter访问)。

二、继承的进一步研究

1.子类对象的实例化

 子类对象在实例化之前,必须先调用父类中的构造方法(super()),之后再调用子类自己的构造方法。(先有爸爸才有孩子)

public class Test {
	
	public static void main(String[] args) {
		Student a = new Student();
		a.setName("xxt");
		a.setAge(22);
		a.setSchool("dufe");
		System.out.println(a.toString());
	}
}

class Person{
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Person() {
		System.out.println("父类中的构造方法。");
	}
}

class Student extends Person{
	private String school;
	public String getSchool() {
		return school;
	}
	public void setSchool(String school) {
		this.school = school;
	}
	public Student() {
		//super();隐含这行,调用父类的无参构造方法。
		System.out.println("子类中的构造方法。");
	}
	@Override
	public String toString() {
		return "Student [school=" + school + ", getName()=" + getName() + ", getAge()=" + getAge() + "]";
	}
}

2.方法覆写:

子类定义了与父类中同名的方法,但是,子类的权限不能比父类严格。

1)覆写方法的调用:默认调用子类,但是想调用父类的话,用super.方法名()

public class Test {
	
	public static void main(String[] args) {
	    Student a = new Student();
	    a.print();	
	}	
}

class Person{
	void print() {
	    System.out.println("父类的方法");
	}
}

class Student extends Person{
	public void print() {
	    super.print();//调用父类中的print()方法
	    System.out.println("子类的方法");
	}
}

2)属性的覆盖:

与方法覆写类似,还存在一种叫做属性的覆盖。

子类父类出现相同属性时,访问时按照“就近访问原则”

public class Test {
	
	public static void main(String[] args) {
		new Student().fun();
	}
}

class Person{
	private void print() {
		System.out.println("父类的方法");
	}
	public void fun() {
		this.print();
	}
}

class Student extends Person{
	void print() {
		System.out.println("子类的方法");
	}
}
//程序运行结果:父类的方法
public class Test {
	
	public static void main(String[] args) {
		new Student().print();
	}
}

class Person{
	public String info = "HHHH";
	
}

class Student extends Person{
	public String info = "AAAA";
	public void print() {
		System.out.println("父类中的属性:"+ super.info);
		System.out.println("子类中的属性:"+ this.info);
		System.out.println("就近的属性:"+ info);
	}
}
//程序运行结果:
//父类中的属性:HHHH
//子类中的属性:AAAA
//就近的属性:AAAA

3)方法重写与重载对比:

3.super关键字:

1)作用:从子类中调用父类的构造方法,普通方法,属性
2)注意事项:super调用父类中制定的构造方法时,必须放在子类构造方法的首行

public class Test {
	
	public static void main(String[] args) {
		Student Monica = new Student("xxt",22,"DUFE");
		System.out.println(Monica.getInfo());
	}
}

class Person{
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Person(String name,int age) {
		this.setName(name);
		this.setAge(age);
	}
	public String getInfo() {
		return "姓名:"+this.getName()+";年龄:"+this.getAge();
	}
}

class Student extends Person{
	private String school;
	public String getSchool() {
		return school;
	}
	public void setSchool(String school) {
		this.school = school;
	}
	public Student(String name,int age,String school) {
		super(name,age);//看这里看这里
		this.setSchool(school);
	}
	public String getInfo() {
		return super.getInfo()+";学校:"+this.getSchool();//还有这里这里
	}
}

3)super与this对比:

注意:无论子类怎么折腾,都必须先调用父类的构造方法。

           因为this和super调用构造时都必须放首行,因此不可共同使用。

三、final关键字:

“完结器”——声明的类,不能有子类;声明的属性,不能被修改(即为常量);声明的方法,不能被重写。

final生命的常量,要求全部字母都大写。如:final String INFO= "xxx";

四、抽象类

1.作用:类的模板,专门当作父类,按照它的格式创建新的派生类。对象不能由抽象类直接创建,可由派生类创建。

2.使用规则:

1)抽象类和抽象方法由abstract关键字声明

2)包含抽象方法的类必须事抽象类

3)抽象方法不需要实现,只需要声明

4)抽象方法不能用private修饰

5)抽象类必须被子继承,子类(如果不是抽象类)必须覆写抽象类中的所有抽象方法。

3.示例:略。实际上抽象类就是比普通类多定义了抽象方法,不可以直接实例化对象,其他的和普通类并无区别。

五、接口

由全局常量+公共的抽象方法组成,可以理解为一种特殊的类。

1.接口定义格式:

interface 接口名称{
    全局常量;
    公共抽象方法;
}

注意:接口中的方法都是public的,即使不写public关键字,默认也是public的。

2.接口示例:

interface Inter1{
	public static final String FLAG = "CHINA";//全局常量
	public abstract void print(); //公共抽象方法
	public abstract String getInfo();//公共抽象方法
}
//简写如下:
interface Inter2{
	String FLAG = "CHINA";
	void print(); 
	String getInfo();
}

注意:由于接口定义中已经知名,接口中的属性都为全局常量,方法都为公共抽象的,因此接口可由Inter1简写Inter2的形式。

3.接口的实现:

1)实现格式:

class 实现类名称 implements 接口A,接口B,...{
    ...
}

由此可见,接口可以摆脱单继承的缺陷。

2)示例:

interface Inter1{
	String AUTHOR = "李兴华";
	void print(); 
	String getInfo();
}

interface Inter2{
	public void say();
}

class X implements Inter1,Inter2{

	@Override
	public void print() {
		// TODO Auto-generated method stub
		System.out.println("Hello,world!");
	}

	@Override
	public String getInfo() {
		// TODO Auto-generated method stub
		return "hello";
	}

	@Override
	public void say() {
		// TODO Auto-generated method stub
		System.out.println("作者:"+ AUTHOR);
	}
	
}

public class Test {
	public static void main(String args[]) {
		X xman = new X();
		xman.print();
		xman.say();
		xman.getInfo();
	}
}

4.实现接口并继承抽象类:

 class X extends A implements B { }

public class Test {
	public static void main(String args[]) {
		X xman = new X();
		xman.print();
		xman.say();
		xman.getInfo();
	}
}

interface A{
	String AUTHOR = "李兴华";
	void print(); 
	String getInfo();
}

abstract class B{
	public abstract void say();
}

class X extends B implements A{

	@Override
	public void print() {
		System.out.println("Hello,world!");
	}

	@Override
	public String getInfo() {
		return "hello";
	}

	@Override
	public void say() {
		System.out.println("作者:"+ AUTHOR);
	}
	
}

注意:接口是可以多继承的,抽象类不行。

六、对象的多态性

Java中面向对象的特征主要两点:1)方法的重写与重载。2)对象的多态性。

1.分类:

对象的多态性分两类:1)对象向上转型: 父类  父类对象 = 子类实例    

                                    2)对象向下转型: 子类 子类对象 = (子类)父类实例

2.示例:

注意:1)向上转型后的对象,所调用的方法一定是被子类覆写过的。不可调用子类中定义但父类中未定义的方法。
           2)向下转型的要求:必须先对象向上转型,然后才可以向下转,否则出现对象转换异常。

public class Test {
	public static void main(String args[]) {
		A a = new B();//向上转型,a可以调用:覆写后的fun1,fun2
		B b = (B)a;//向下转型,b可以调用:覆写过的fun1,fun2,fun3
		a.fun1();//输出:子类中的fun1
		a.fun2();//输出:子类中的fun1
		b.fun1();//输出:子类中的fun1
		b.fun2();//输出:子类中的fun1
		b.fun3();//输出:子类中的fun3
	}
}

class A{
	public void fun1() {
		System.out.println("父类中的fun1");
	}
	public void fun2() {
		this.fun1();
	}
}

class B extends A{
	public void fun1() {
		System.out.println("子类中的fun1");
	}
	public void fun3() {
		System.out.println("子类中的fun3");
	}
}

七、instanceOf关键字

1.作用:判断对象是哪个类的实例

2.格式:对象 instanceof  类  →  返回Boolean

3.示例:

public class Test {
	public static void main(String args[]) {
		A a1 = new B();
		System.out.println(" A a1 = new B():" + (a1 instanceof A));//true
		System.out.println(" A a1 = new B():" + (a1 instanceof B));//true
		A a2 = new A();
		System.out.println(" A a2 = new A():" + (a2 instanceof A));//true
		System.out.println(" A a2 = new A():" + (a2 instanceof B));//false
	}
}

class A{
	public void fun1() {
		System.out.println("父类中的fun1");
	}
	public void fun2() {
		this.fun1();
	}
}

class B extends A{
	public void fun1() {
		System.out.println("子类中的fun1");
	}
	public void fun3() {
		System.out.println("子类中的fun3");
	}
}

由此可见,向上转型都true,向下转型就不行了。

因此,instanceof 的一个功能就是:在做向下转型之前进行判断,这样可以避免类型转换异常。

4.向下转型前的判断:

public class Test {
	public static void main(String args[]) {
		fun(new B());
		fun(new C());
	}
	
	public static void fun(A a) {//判断是哪个子类,然后调用该子类自己的方法。
		a.fun1();
		if(a instanceof B) {
			B b = (B)a;
			b.fun3();
		}
		if(a instanceof C) {
			C c = (C)a;
			c.fun4();
		}
	}
}

class A{
	public void fun1() {
		System.out.println("A中的fun1");
	}
	public void fun2() {
		this.fun1();
	}
}

class B extends A{
	public void fun1() {
		System.out.println("B中的fun1");
	}
	public void fun3() {
		System.out.println("B中的fun3");
	}
}

class C extends A{
	public void fun1() {
		System.out.println("C中的fun1");
	}
	public void fun4() {
		System.out.println("C中的fun3");
	}
}

八、抽象类和接口的应用

1.抽象类的实际应用——模板设计

抽象类相当于定义了一个模板,在主方法中调用它的普通方法(该普通方法调用了自身的抽象方法),而子类只需要实现其抽象方法,就可以取得一个具体的信息。

示例:

public class Test {
	public static void main(String args[]) {
		Person p1 = new Student("张三",20,90.0f);
		Person p2 = new Worker("李四",30,6000.0f);
		p1.say();
		p2.say();
	}
}

abstract class Person{
	//属性
	private String name;
	private int age;
	//构造器
	public Person(String name,int age) {
		this.name = name;
		this.age = age;
	}
	//getter
	public String getName() {
		return name;
	}
	public int getAge() {
		return age;
	}
	//抽象方法
	abstract String getContent();
	//调用抽象方法的普通方法
	public void say() {
		System.out.println(this.getContent());
	}
}

class Student extends Person{
	//属性
	private float score;
	//构造器
	public Student(String name, int age,float score) {
		super(name, age);
		this.score = score;
	}
	//getter
	public float getScore() {
		return score;
	}
	//重写抽象方法
	@Override
	String getContent() {
		return "学生信息-->姓名:"+this.getName()+",年龄:"
				+this.getAge()+",成绩:"+this.getScore();
	}
}

class Worker extends Person{
	//属性
	private float salary;
	//构造器
	public Worker(String name, int age,float salary) {
		super(name, age);
		this.salary = salary;
	}
	//getter
	public float getSalary() {
		return salary;
	}
	//重写抽象方法
	@Override
	String getContent() {
		return "工人信息-->姓名:"+this.getName()+",年龄:"
				+this.getAge()+",薪资:"+this.getSalary();
	}
}

2.接口的实际应用——制定标准

如下例,接口就是一个标准,只要符合这个标准,电脑就可以插入,不管你插入的是U盘还是打印机还是其它。

示例:

public class Test {
	public static void main(String args[]) {
		Flash f = new Flash();
		Computer.plugin(f);//插入U盘
		Print p = new Print();
		Computer.plugin(p);//插入打印机
	}
}
//USB接口
interface USB{
	public void start();
	public void stop();
}
//U盘实现了USB接口
class Flash implements USB{

	@Override
	public void start() {
		System.out.println("U盘开始工作。");
	}

	@Override
	public void stop() {
		System.out.println("U盘停止工作。");		
	}
}
//打印机实现了USB接口
class Print implements USB{

	@Override
	public void start() {
		System.out.println("打印机开始工作。");
	}

	@Override
	public void stop() {
		System.out.println("打印机停止工作。");
	}
}
//电脑可以插入USB设备
class Computer{
	public static void plugin(USB usb) {
		usb.start();
		System.out.println("===USB设备工作中===");
		usb.stop();
	}
}

九、内部类的扩展

一句话,抽象类中可以定义多个内部抽象类和接口;接口中也可以定义多个内部抽象类和接口。

十、抽象类VS接口

十一、实例分析:宠物商店

设计一个宠物商店,里面有多种宠物(暂定猫、狗),每只宠物有名称、颜色、年龄三种属性。在商店中,只要满足此宠物标准的都可以放入宠物店内,且提供根据宠物名称进行模糊查询,查询结果返回宠物的全部属性信息。

分析:

1.”宠物“是个标准 → interface。

2.“猫、狗” → 实体类两个,且都有名称、颜色、年龄三种属性,那么就得有相应的构造方法和getter方法。因此宠物interface中就得有getter的抽象方法。

3.”宠物商店“是一个存放宠物的数组。里面得包括 添加一只宠物的方法、按名称模糊查询宠物信息的方法(该方法返回值也是一个宠物类型的数组)。

4.其他:interface中的抽象方法,用到谁写谁,估计只能用到getName()。

              输出查询结果信息时,估计会需要重写toString()。

              确定数组长度时会比较烦,注意一下。

实现:

代码已实现,懒得贴了。

 

 

 

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值