JAVA面向对象

JAVA面向对象

第一部分

1. 面向对象思想

我们考虑使用类封装多个方法,将来再做数组的操作时,不用去找具体的操作方法,先找到这个类,然后使用这个类中的方法。这就是面向对象思想的编程方式。
面向对象:
我们怎么才能更符合面向对象思想呢?
A:有哪些类呢?
B:每个类有哪些东西呢?
C:类与类直接的关系是什么呢?

	把大象装进冰箱的分析? (如何分析有哪些类呢?UML。名词提取法。)
		A:有哪些类呢?
			大象
			冰箱
			Demo
		B:每个类有哪些东西呢?
			大象:
				进去
			冰箱:
				开门
				关门
			Demo:
				main方法
		C:类与类直接的关系是什么呢?
			Demo中使用大象和冰箱类的功能。
			
	代码体现:
		class 大象 {
			public static void in() {
				System.out.println("装进大象");
			}
		}
		
		class 冰箱 {
			public static void open() {
				System.out.println("打开冰箱门");
			}
			
			public static void close() {
				System.out.println("关闭冰箱门");
			}
		}
		
		class Demo {
			public static void main(String[] args) {
				冰箱调用开门
				大象调用进去
				冰箱调用关门
			}
		}

开发,设计,特征
面向对象开发
就是不断的创建对象,使用对象,指挥对象做事情。

面向对象设计
其实就是在管理和维护对象之间的关系。

面向对象特征
封装(encapsulation)
继承(inheritance)
多态(polymorphism)

2. 类与对象及其使用

A:现实世界的事物
属性 事物的基本描述
行为 事物的功能
B:Java语言中最基本的单位是类。所以,我们要用类来体现事物
C:类
成员变量 事物属性
成员方法 事物行为
D:类:是一组相关的属性和行为的集合。是一个抽象的概念。
对象:是该类事物的具体存在,是一个具体的实例。(对象)
举例:
学生:类
班长:对象

3. 成员变量和局部变量的区别

在类中的位置不同 成员变量 类中方法外 局部变量 方法内或者方法声明上 在内存中的位置不同 成员变量 堆内存 局部变量 栈内存 生命周期不同 成员变量 随着对象的存在而存在,随着对象的消失而消失 局部变量 随着方法的调用而存在,随着方法的调用完毕而消失 初始化值不同 成员变量 有默认的初始化值 局部变量 没有默认的初始化值,必须先定义,赋值,才能使用。
注意事项
局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则

4. 匿名对象

匿名对象:就是没有名字的对象。 是对象的一种简化表示形式
匿名对象的两种使用情况
1.对象调用方法仅仅一次的时候 new student( ).method( );
2.作为实际参数传递 sd.method(new student( ));

5. 封装

怎么去强制要求不能直接使用成员变量呢?
针对这种情况,Java就提供了一个关键字 private

private:私有的。可以修饰成员变量和成员方法。
	注意:被private修饰的成员只能在本类中访问。
	
其实我讲到现在讲解的是一个封装的思想。
封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

好处: 隐藏实现细节,提供公共的访问方式
提高了代码的复用性 提高安全性。
封装原则: 将不需要对外提供的内容都隐藏起来。 把属性隐藏,提供公共方法对其访问。

6. private关键字

private关键字: 是一个权限修饰符。 可以修饰成员(成员变量和成员方法) 被private修饰的成员只在本类中才能访问。 private最常见的应用: 把成员变量用private修饰 提供对应的getXxx()/setXxx()方法 一个标准的案例的使用

private String name;
//姓名获取值
public String getName() {
return name;
}

//姓名设置值
public void setName(String n) {
name = n;
}

7. this关键字

方法被哪个对象调用,this就代表那个对象 什么时候使用this呢? 局部变量隐藏成员变量 其他用法后面和super一起讲解

public String getName() {
		return name;   // 这里隐藏了this
	}
private String name;
public void setName(String name) { //name = "林青霞";
		this.name = name;
}

8. 构造方法

构造方法作用概述 给对象的数据进行初始化
构造方法格式 方法名与类名相同 没有返回值类型,连void都没有 没有具体的返回值
构造方法的注意事项:
A:如果我们没有给出构造方法,系统将自动提供一个无参构造方法。
B:如果我们给出了构造方法,系统将不再提供默认的无参构造方法。
C:构造方法也是可以重载的
注意:这个时候,如果我们还想使用无参构造方法,就必须自己给出。建议永远自己给出无参构造方法

给成员变量赋值有两种方式:
	A:setXxx()        B:构造方法

9. 类的初始化过程

Static关键字**
(1) static的特点:(它可以修饰成员变量,还可以修饰成员方法)
A:随着类的加载而加载
回想main方法。
B:优先于对象存在
C:被类的所有对象共享
举例:咱们班级的学生应该共用同一个班级编号。
其实这个特点也是在告诉我们什么时候使用静态?
如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的。
举例:
班级饮水机(用静态修饰)
学生水杯(不能用静态修饰)
D: 可以通过类名调用
其实它本身也可以通过对象名调用。
推荐使用类名调用。
静态修饰的内容一般我们称其为:与类相关的,类成员
*/

class Student {
//非静态变量
int num = 10;

//静态变量
static int num2 = 20;

}

class StudentDemo {
public static void main(String[] args) {
Student s = new Student();
System.out.println(s.num);

	System.out.println(Student.num2);
	System.out.println(s.num2);
}

}
例1
String name;
//年龄
int age;
//国籍
//String country;
static String country;

public Person(){}

public Person(String name,int age) {
	this.name = name;
	this.age = age;
}

public Person(String name,int age,String country) {
	this.name = name;
	this.age = age;
	this.country = country;
}

public void show() {
	System.out.println("姓名:"+name+",年龄:"+age+",国籍:"+country);
}

Person p1 = new Person(“邓丽君”,16,“中国”);
p1.show(); // 邓丽君",16,"中国

	Person p2 = new Person("杨幂",22);
	p2.show();     //   杨幂",22,"中国
	 
	Person p3 = new Person("凤姐",20);
	p3.show();    //    凤姐",20,"中国	

	p3.country = "美国";
	p3.show();    //    凤姐",20,美国
	p1.show();    //   邓丽君",16, 美国
	p2.show();     //   杨幂",22, 美国

(2) static关键字注意事项
A:在静态方法中是没有this关键字的
如何理解呢?
静态是随着类的加载而加载,this是随着对象的创建而存在。
静态比对象先存在。
B:静态方法只能访问静态的成员变量和静态的成员方法
静态方法:
成员变量:只能访问静态变量
成员方法:只能访问静态成员方法
非静态方法:
成员变量:可以是静态的,也可以是非静态的
成员方法:可是是静态的成员方法,也可以是非静态的成员方法。
简单记:
静态只能访问静态。

class Teacher {
	public int num = 10;
	public static int num2 = 20;
	
	public void show() {
    		System.out.println(num); //隐含的告诉你访问的是成员变量
    		System.out.println(this.num); //明确的告诉你访问的是成员变量
    		System.out.println(num2);
    		
    		//function();
    		//function2();
    	}
	
	public static void method() {
		//无法从静态上下文中引用非静态 变量 num
		//System.out.println(num);
		System.out.println(num2);
		
		//无法从静态上下文中引用非静态 方法 function()
		//function();
		function2();
	}
	
	public void function() {
	
	}
	
	public static void function2() {
	
	}
}

class TeacherDemo {
	public static void main(String[] args) {
		//创建对象
		Teacher t = new Teacher();
		t.show();
		System.out.println("------------");
		t.method();
	}
}

10. 静态变量和成员变量的区别

所属不同 : 静态变量属于类,所以也称为为类变量 成员变量属于对象,所以也称为实例变量(对象变量)
内存中位置不同: 静态变量存储于方法区的静态区 成员变量存储于堆内存
内存出现时间不同 : 静态变量随着类的加载而加载,随着类的消失而消失 成员变量随着对象的创建而存在,随着对象的消失而消失
调用不同: 静态变量可以通过类名调用,也可以通过对象调用 成员变量只能通过对象名调用

第二部分

**

1. Main方法调用方法

**
Main是静态的,只能调用静态的方法,若调用非静态的通过类对象调用非静态方法
ArrayDemo.java

 class ArrayDemo {
	public static void main(String[] args) {
		//定义数组
		int[] arr = {28,55,37,46,19};
		
		//需求:遍历数组
		/*
		for(int x=0; x<arr.length; x++) {
			if(x == arr.length-1) {
				System.out.println(arr[x]);
			}else {
				System.out.pri  nt(arr[x]+", ");
			}
		}
		*/
		
		//如果我有多个数组都要进行遍历,那么,代码的重复度就很高
		//如何改进呢?用方法改进
		//调用
		//静态方法
		//printArray(arr);
	
	//非静态方法
	//ArrayDemo ad = new ArrayDemo();
	//ad.printArray(arr);
	
	//测试类的作用:创建其他类的对象,调用其他类的功能。
	//而我们现在的操作是跟数组相关的,所以,你应该把这些操作定义到数组操作类中
	//定义一个数组的操作类
	//有了数组操作类之后的调用
	//ArrayTool at = new ArrayTool();
	//at.printArray(arr);
	
	//方法改进为静态后,就可以直接通过类名调用
	ArrayTool.printArray(arr);
}

/*
public static void printArray(int[] arr) {
	for(int x=0; x<arr.length; x++) {
		if(x == arr.length-1) {
			System.out.println(arr[x]);
		}else {
			System.out.print(arr[x]+", ");
		}
	}
}
*/

//假设该方法不是静态的
/*
public void printArray(int[] arr) {
	for(int x=0; x<arr.length; x++) {
		if(x == arr.length-1) {
			System.out.println(arr[x]);
		}else {
			System.out.print(arr[x]+", ");
		}
	}
}
*/

}
ArrayTool.java

class ArrayTool {
	
    	//把构造方法私有,外界就不能在创建对象了
    	private ArrayTool(){}
    
    	public static void printArray(int[] arr) {
		for(int x=0; x<arr.length; x++) {
			if(x == arr.length-1) {
				System.out.println(arr[x]);
			}else {
				System.out.print(arr[x]+", ");
			}
		}
	}
}

2. 帮助文档

1:如何制作帮助文档(了解)
(1)写一个类
(2)加入文档注释
(3)通过javadoc工具生成即可
javadoc -d 目录 -author -version ArrayTool.java

2:如何使用帮助文档

1:打开帮助文档
2:点击显示,找到索引,看到输入框
3:知道你要找谁?以Scanner举例
4:在输入框里面输入Scanner,然后回车
5:看包
java.lang包下的类不需要导入,其他的全部需要导入。

要导入:
java.util.Scanner

6:再简单的看看类的解释和说明,别忘了看看该类的版本
7:看类的结构
成员变量 字段摘要
构造方法 构造方法摘要
成员方法 方法摘要
8:学习构造方法
A:有构造方法 就创建对象
B:没有构造方法 成员可能都是静态的
9:看成员方法
A:左边
是否静态:如果静态,可以通过类名调用
返回值类型:人家返回什么,你就用什么接收。
B:右边
看方法名:方法名称不要写错
参数列表:人家要什么,你就给什么;人家要几个,你就给几个

3. 代码块

/*
代码块:在Java中,使用{}括起来的代码被称为代码块。
根据其位置和声明的不同,可以分为
局部代码块:局部位置,用于限定变量的生命周期。
构造代码块:在类中的成员位置,用{}括起来的代码。每次调用构造方法执行前,都会先执行构造代码块。
作用:可以把多个构造方法中的共同代码放到一起,对对象进行初始化。
静态代码块:在类中的成员位置,用{}括起来的代码,只不过它用static修饰了。
作用:一般是对类进行初始化。

面试题?
	静态代码块,构造代码块,构造方法的执行顺序?
	静态代码块 -- 构造代码块 -- 构造方法
	静态代码块:只执行一次
	构造代码块:每次调用构造方法都执行

*/

  class Code {
    	static {
    		int a = 1000;
    		System.out.println(a);
    	}
    
    	//构造代码块
    	{
		int x = 100;
		System.out.println(x);
	}
	
    	//构造方法
    	public Code(){
    		System.out.println("code");
    	}
	
	//构造方法
	public Code(int a){
		System.out.println("code");
	}
	
	//构造代码块
	{
		int y = 200;
		System.out.println(y);
	}
	
	//静态代码块
	static {
		int b = 2000;
		System.out.println(b);
	}
}
    
class CodeDemo {
	public static void main(String[] args) {
		//局部代码块
		{
			int x = 10;
			System.out.println(x);
		}
		//找不到符号
		//System.out.println(x);
		{
			int y = 20;
			System.out.println(y);
		}
		System.out.println("---------------");
		
    		Code c = new Code();	
    		System.out.println("---------------");
    		Code c2 = new Code();
    		System.out.println("---------------");
    		Code c3 = new Code(1);
    	}
    }

例1:
    /*
	写程序的执行结果。
	
	林青霞都60了,我很伤心
	我是main方法
	Student 静态代码块
	Student 构造代码块
	Student 构造方法
	Student 构造代码块
	Student 构造方法
*/
class Student {
	static {
		System.out.println("Student 静态代码块");
	}
	
	{
		System.out.println("Student 构造代码块");
	}
	
	public Student() {
		System.out.println("Student 构造方法");
	}
}

class StudentDemo {
	static {
		System.out.println("林青霞都60了,我很伤心");
	}
	
	public static void main(String[] args) {
		System.out.println("我是main方法");
		
		Student s1 = new Student();
		Student s2 = new Student();
	}
}

第三部分

继承
(1)继承概述
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。 通过extends关键字可以实现类与类的继承 class 子类名 extends 父类名 {} 单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。 有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员。
(2)继承的好处
提高了代码的复用性 多个类相同的成员可以放到同一个类中 提高了代码的维护性 如果功能的代码需要修改,修改一处即可 让类与类之间产生了关系,是多态的前提
其实这也是继承的一个弊端:类的耦合性很强
(3)开发的原则: 底耦合,高内聚
耦合: 类与类之间的关系
内聚: 就是完成某件事的能力

(4)Java中继承的特点 Java只支持单继承,不支持多继承
Java支持多层继承(继承体系)
(5)Java中继承的注意事项
子类只能继承父类所有非私有的成员(成员方法和成员变量) 其实这也体现了继承的另一个弊端:打破了封装性 子类不能继承父类的构造方法,但是可以通过super(后面讲)关键字去访问父类构造方法。 不要为了部分功能而去继承 我们到底在什么时候使用继承呢? 继承中类之间体现的是:”is a”的关系

(6)继承中成员变量的关系
在子类方法中访问一个变量 首先在子类局部范围找 然后在子类成员范围找 最后在父类成员范围找(肯定不能访问到父类局部范围) 如果还是没有就报错。(不考虑父亲的父亲…)

(7)super关键字
问题是:
我不仅仅要输出局部范围的num,还要输出本类成员范围的num。怎么办呢?
我还想要输出父类成员范围的num。怎么办呢?
如果有一个东西和this相似,但是可以直接访问父类的数据就好了。
恭喜你,这个关键字是存在的:super。
this和super的区别?
分别是什么呢?
this代表本类对应的引用。
super代表父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)
怎么用呢?
A:调用成员变量
this.成员变量 调用本类的成员变量
super.成员变量 调用父类的成员变量
B:调用构造方法
this(…) 调用本类的构造方法
super(…) 调用父类的构造方法
C:调用成员方法
this.成员方法 调用本类的成员方法
super.成员方法 调用父类的成员方法

class Father {
	public int num = 10;
}

class Son extends Father {
	public int num = 20;
	
	public void show() {
		int num = 30;
		System.out.println(num);
		System.out.println(this.num);
		System.out.println(super.num);
	}
}

class ExtendsDemo5 {
	public static void main(String[] args) {
		Son s = new Son();
		s.show();
	}
}

(8)继承中构造方法的关系
继承中构造方法的关系
A:子类中所有的构造方法默认都会访问父类中空参数的构造方法
B:为什么呢?
因为子类会继承父类中的数据,可能还会使用父类的数据。
所以,子类初始化之前,一定要先完成父类数据的初始化。

		注意:子类每一个构造方法的第一条语句默认都是:super();
		
class Father {
	int age;

	public Father() {
		System.out.println("Father的无参构造方法");
	}
	
	public Father(String name) {
		System.out.println("Father的带参构造方法");
	}
}

class Son extends Father {
	public Son() {
		//super();
		System.out.println("Son的无参构造方法");
	}
	
	public Son(String name) {
		//super();
		System.out.println("Son的带参构造方法");
	}
}	

class ExtendsDemo6 {
	public static void main(String[] args) {
		//创建对象
		Son s = new Son();
		System.out.println("------------");
		Son s2 = new Son("林青霞");
	}
}

(9)继承中构造方法的注意事项
/*
如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢?
报错。
如何解决呢?
A:在父类中加一个无参构造方法
B:通过使用super关键字去显示的调用父类的带参构造方法
C:子类通过this去调用本类的其他构造方法
子类中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化。

注意事项:
	this(...)或者super(...)必须出现在第一条语句上。
	如果不是放在第一条语句上,就可能对父类的数据进行了多次初始化,所以必须放在第一条语句上。

*/

class Father {
	/*
	public Father() {
		System.out.println("Father的无参构造方法");
	}
	*/
	
	public Father(String name) {
		System.out.println("Father的带参构造方法");
	}
}

class Son extends Father {
	public Son() {
		super("随便给");
		System.out.println("Son的无参构造方法");
		//super("随便给");
	}
	
	public Son(String name) {
		//super("随便给");
		this();
		System.out.println("Son的带参构造方法");
	}
}

class ExtendsDemo7 {
	public static void main(String[] args) {
		Son s = new Son();
		System.out.println("----------------");
		Son ss = new Son("林青霞");
	}
}

(10) 面试题
例1 看程序写结果:
A:成员变量 就近原则
B:this和super的问题
this访问本类的成员
super访问父类的成员
C:子类构造方法执行前默认先执行父类的无参构造方法
D:一个类的初始化过程
成员变量进行初始化
默认初始化
显示初始化
构造方法初始化

结果:
	fu
	zi
	30
	20
	10

*/

class Fu{
	public int num = 10;
	public Fu(){
		System.out.println("fu");
	}
}
class Zi extends Fu{
	public int num = 20;
	public Zi(){
		System.out.println("zi");
	}
	public void show(){
		int num = 30;
		System.out.println(num); //30
		System.out.println(this.num); //20
		System.out.println(super.num); //10
	}
}
class ExtendsTest {
	public static void main(String[] args) {
		Zi z = new Zi();
		z.show();
	}
}

例2 看程序写结果:
A:一个类的静态代码块,构造代码块,构造方法的执行流程
静态代码块 > 构造代码块 > 构造方法
B:静态的内容是随着类的加载而加载
静态代码块的内容会优先执行
C:子类初始化之前先会进行父类的初始化

结果是:
	静态代码块Fu
	静态代码块Zi
	构造代码块Fu
	构造方法Fu
	构造代码块Zi
	构造方法Zi


class Fu {
	static {
		System.out.println("静态代码块Fu");
	}

	{
		System.out.println("构造代码块Fu");
	}

	public Fu() {
		System.out.println("构造方法Fu");
	}
}

class Zi extends Fu {
	static {
		System.out.println("静态代码块Zi");
	}

	{
		System.out.println("构造代码块Zi");
	}

	public Zi() {
		System.out.println("构造方法Zi");
	}
}

class ExtendsTest2 {
	public static void main(String[] args) {
		Zi z = new Zi();
	}
}

例3:看程序写结果:

看程序写结果:
	A:成员变量的问题
		int x = 10; //成员变量是基本类型
		Student s = new Student(); //成员变量是引用类型
	B:一个类的初始化过程
		成员变量的初始化
			默认初始化
			显示初始化
			构造方法初始化
	C:子父类的初始化(分层初始化)
		先进行父类初始化,然后进行子类初始化。
		
结果:
	YXYZ
	
问题:
	虽然子类中构造方法默认有一个super()
	初始化的时候,不是按照那个顺序进行的。
	而是按照分层初始化进行的。
	它仅仅表示要先初始化父类数据,再初始化子类数据。


class X {
	Y b = new Y();
	X() {
		System.out.print("X");
	}
}

class Y {
	Y() {
		System.out.print("Y");
	}
}

public class Z extends X {
	Y y = new Y();
	Z() {
		//super
		System.out.print("Z");
	}
	public static void main(String[] args) {
		new Z(); 
	}
}

(11)继承中成员方法的关系
方法重写概述 子类中出现了和父类中一模一样的方法声明,也被称为方法覆盖,方法复写。 使用特点: 如果方法名不同,就调用对应的方法 如果方法名相同,最终使用的是子类自己的 方法重写的应用: 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的
方法,这样,即沿袭了父类的功能,又定义了子类特有的内容。 案例:
A:定义一个手机类。
B:通过研究,我发明了一个新手机,这个手机的作用是在打完电话后,可以听天气预报。
按照我们基本的设计,我们把代码给写出来了。
但是呢?我们又发现新手机应该是手机,所以,它应该继承自手机。
其实这个时候的设计,并不是最好的。
因为手机打电话功能,是手机本身就具备的最基本的功能。
所以,我的新手机是不用在提供这个功能的。
但是,这个时候,打电话功能就没有了。这个不好。
最终,还是加上这个功能。由于它继承了手机类,所以,我们就直接使用父类的功能即可。
那么,如何使用父类的功能呢?通过super关键字调用
*/

class Phone {
	public void call(String name) {
		System.out.println("给"+name+"打电话");
	}
}

class NewPhone extends Phone {
	public void call(String name) {
		//System.out.println("给"+name+"打电话");
		super.call(name);
		System.out.println("可以听天气预报了");
	}
}

class ExtendsDemo9 {
	public static void main(String[] args) {
		NewPhone np = new NewPhone();
		np.call("林青霞");
	}
}

(12) 方法重写的注意事项
父类中私有方法不能被重写 子类重写父类方法时,访问权限不能更低 父类静态方法,子类也必须通过静态方法进行重写。(其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解) 子类重写父类方法的时候,最好声明一模一样

(13) 两个面试题
1:方法重写和方法重载的区别?方法重载能改变返回值类型吗?

方法重写:
在子类中,出现和父类中一模一样的方法声明的现象。

方法重载:
同一个类中,出现的方法名相同,参数列表不同的现象。

方法重载能改变返回值类型,因为它和返回值类型无关。

Override:方法重写
Overload:方法重载

2:this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。

this:代表当前类的对象引用
super:代表父类存储空间的标识。(可以理解为父类的引用,通过这个东西可以访问父类的成员)

场景:
成员变量:
this.成员变量
super.成员变量
构造方法:
this(…)
super(…)
成员方法:
this.成员方法
super.成员方法

例题

 /*
猫狗案例讲解

先找到具体的事物,然后发现具体的事物有共性,才提取出一个父类。

猫:
	成员变量:姓名,年龄,颜色
	构造方法:无参,带参
	成员方法:
		getXxx()/setXxx()
		eat()
		palyGame()
狗:
	成员变量:姓名,年龄,颜色
	构造方法:无参,带参
	成员方法:
		getXxx()/setXxx()
		eat()
		lookDoor()
		
共性:
	成员变量:姓名,年龄,颜色
	构造方法:无参,带参
	成员方法:
		getXxx()/setXxx()
		eat()
		
把共性定义到一个类中,这个类的名字叫:动物。
动物类:
	成员变量:姓名,年龄,颜色
	构造方法:无参,带参
	成员方法:
		getXxx()/setXxx()
		eat()
		
	猫:	
		构造方法:无参,带参
		成员方法:palyGame()
	狗:
		构造方法:无参,带参
		成员方法:lookDoor()

*/
//定义动物类

class Animal {
	//姓名
	private String name;
	//年龄
	private int age;
	//颜色
	private String color;
	
	public Animal() {}
	
	public Animal(String name,int age,String color) {
		this.name = name;
		this.age = age;
	this.color = color;
}

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 String getColor() {
	return color;
}

public void setColor(String color) {
	this.color = color;
}

public void eat() {
	System.out.println("不要睡了,该吃饭了");
}

}

//定义猫类

class Cat extends Animal {
	public Cat() {}
	
	public Cat(String name,int age,String color) {
		super(name,age,color);
	}
	
	public void playGame() {
		System.out.println("猫玩英雄联盟");
	}
}

//定义狗类

class Dog extends Animal {
	public Dog() {}
	
	public Dog(String name,int age,String color) {
		super(name,age,color);
	}
	
	public void lookDoor() {
		System.out.println("狗看家");
	}
}

//测试类

class ExtendsTest5 {
	public static void main(String[] args) {
		//测试猫
		//方式1
		Cat c1 = new Cat();
		c1.setName("Tom");
		c1.setAge(3);
		c1.setColor("白色");
		System.out.println("猫的名字是:"+c1.getName()+";年龄是:"+c1.getAge()+";颜色是:"+c1.getColor());
		c1.eat();
		c1.playGame();
		System.out.println("---------------");
	
	//方式2
	Cat c2 = new Cat("杰瑞",5,"土豪金");
	System.out.println("猫的名字是:"+c2.getName()+";年龄是:"+c2.getAge()+";颜色是:"+c2.getColor());
	c2.eat();
	c2.playGame();
	
}

}

3 final 关键字

(1)final可以修饰类,方法,变量
特点:
final可以修饰类,该类不能被继承。
final可以修饰方法,该方法不能被重写。(覆盖,复写)
final可以修饰变量,该变量不能被重新赋值。因为这个变量其实常量。

常量:
	A:字面值常量
		"hello",10,true
	B:自定义常量
		final int x = 10;

*/

//final class Fu //无法从最终Fu进行继承

class Fu {
	public int num = 10;
	public final int num2 = 20;

	/*
	public final void show() {
	
	}
	*/
}

class Zi extends Fu {
	// Zi中的show()无法覆盖Fu中的show()
	public void show() {
		num = 100;
		System.out.println(num);
		
		//无法为最终变量num2分配值
		//num2 = 200;
		System.out.println(num2);
	}
}

class FinalDemo {
	public static void main(String[] args) {
		Zi z = new Zi();
		z.show();
	}
}

(2) final 面试题
面试题1 :final修饰局部变量的问题
基本类型:基本类型的值不能发生改变。
引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的。
*/

class Student {
	int age = 10;
}

class FinalTest {
	public static void main(String[] args) {
		//局部变量是基本数据类型
		int x = 10;
		x = 100;
		System.out.println(x);
		final int y = 10;
		//无法为最终变量y分配值
		//y = 100;
		System.out.println(y);
		System.out.println("--------------");
		
		//局部变量是引用数据类型
		Student s = new Student();
		System.out.println(s.age);
		s.age = 100;
		System.out.println(s.age);
		System.out.println("--------------");
		
		final Student ss = new Student();
		System.out.println(ss.age);
		ss.age = 100;
		System.out.println(ss.age);
		
		//重新分配内存空间
		//无法为最终变量ss分配值
		//ss = new Student();   //  报错
	}
}

面试题2 :final修饰变量的初始化时机 final修饰变量的初始化时机
A:被final修饰的变量只能赋值一次。
B:在构造方法完毕前。(非静态的常量)

class Demo {
	//int num = 10;
	//final int num2 = 20;
	
	int num;
	final int num2;
	
	{
		//num2 = 10;
	}
	
	public Demo() {
		num = 100;
		//无法为最终变量num2分配值
		num2 = 200;
	}
}

class FinalTest2 {
	public static void main(String[] args) {
		Demo d = new Demo();
		System.out.println(d.num);
		System.out.println(d.num2);
	}
}

第四部分

多态
多态概述 某一个事物,在不同时刻表现出来的不同状态。
举例: 猫可以是猫的类型。猫 m = new 猫(); 同时猫也是动物的一种,也可以把猫称为动物。 动物 d = new 猫(); 在举一个例子:水在不同时刻的状态

多态前提和体现 有继承关系 有方法重写 有父类引用指向子类对象
(1)多态中成员访问特点
A:成员变量
编译看左边,运行看左边。
B:构造方法
创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。
C:成员方法
编译看左边,运行看右边。(重写的成员方法)
编译看左边,运行看左边。(父类自己的成员方法)
D:静态方法
编译看左边,运行看左边。
(静态和类相关,算不上重写,所以,访问还是左边的)

	由于成员方法存在方法重写,所以它运行看右边。

class Fu {
public int num = 100;

public void show() {
	System.out.println("show Fu");
}

public static void function() {
	System.out.println("function Fu");
}

}

class Zi extends Fu {
public int num = 1000;
public int num2 = 200;

public void show() {
	System.out.println("show Zi");
}

public void method() {
	System.out.println("method zi");
}

public static void function() {
	System.out.println("function Zi");
}

}

class DuoTaiDemo {
public static void main(String[] args) {
//要有父类引用指向子类对象。
//父 f = new 子();
Fu f = new Zi();
System.out.println(f.num);
//找不到符号
//System.out.println(f.num2);

	f.show();
	//找不到符号
	//f.method();
	f.function();
}

}

(2) 多态的好处与弊端

提高了程序的维护性(由继承保证) 提高了程序的扩展性(由多态保证) 弊端:不能访问子类特有功能
class AnimalTool {
private AnimalTool(){}

/*
//调用猫的功能
public static void useCat(Cat c) {
	c.eat();
	c.sleep();
}

//调用狗的功能
public static void useDog(Dog d) {
	d.eat();
	d.sleep();
}

//调用猪的功能
public static void usePig(Pig p) {
	p.eat();
	p.sleep();
}
*/
public static void useAnimal(Animal a) {
	a.eat();
	a.sleep();
}

}

(3) 多态中的向下转型
多态的弊端:
不能使用子类的特有功能。

我就想使用子类的特有功能?行不行?
	行。
	
怎么用呢?
	A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)
	B:把父类的引用强制转换为子类的引用。(向下转型)
	
对象间的转型问题:
	向上转型:
		Fu f = new Zi();
	向下转型:
		Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。

class DuoTaiDemo4 {
public static void main(String[] args) {
//测试
Fu f = new Zi();
f.show();
//f.method();

	//创建子类对象
	//Zi z = new Zi();
	//z.show();
	//z.method();
	
	//你能够把子的对象赋值给父亲,那么我能不能把父的引用赋值给子的引用呢?
	//如果可以,但是如下
	Zi z = (Zi)f;
	z.show();
	z.method();
}

}

转型过程中出现的错误

	Animal a = new Dog();
	Dog d = (Dog)a;
	
	//内存中是猫
	a = new Cat();
	Cat c = (Cat)a;
	
	//内存中是猫
	Dog dd = (Dog)a; //ClassCastException   报错

(4) 例题
class A {
public void show() {
show2();
}
public void show2() {
System.out.println(“我”);
}
}
class B extends A {
/*
public void show() {
show2();
}
*/

public void show2() {
	System.out.println("爱");
}

}
class C extends B {
public void show() {
super.show();
}
public void show2() {
System.out.println(“你”);
}
}
public class DuoTaiTest4 {
public static void main(String[] args) {
A a = new B();
a.show(); // 爱

	B b = new C();
	b.show();     //  你
}

}

抽象类
抽象类的概述:
动物不应该定义为具体的东西,而且动物中的吃,睡等也不应该是具体的。
我们把一个不是具体的功能称为抽象的功能,而一个类中如果有抽象的功能,该类必须是抽象类。

 抽象类的特点:
	A:抽象类和抽象方法必须用abstract关键字修饰
	B:抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类
	C:抽象类不能实例化
		因为它不是具体的。
		抽象类有构造方法,但是不能实例化?构造方法的作用是什么呢?
		用于子类访问父类数据的初始化
	D:抽象的子类
		a:如果不想重写抽象方法,该子类是一个抽象类。
		b:重写所有的抽象方法,这个时候子类是一个具体的类。
		
	抽象类的实例化其实是靠具体的子类实现的。是多态的方式。
		Animal a = new Cat();

abstract class Animal {
//抽象方法
//public abstract void eat(){} //空方法体,这个会报错。抽象方法不能有主体
public abstract void eat();

public Animal(){}

}

//子类是抽象类
abstract class Dog extends Animal {}

//子类是具体类,重写抽象方法
class Cat extends Animal {
public void eat() {
System.out.println(“猫吃鱼”);
}
}

class AbstractDemo {
public static void main(String[] args) {
//创建对象
//Animal是抽象的; 无法实例化
//Animal a = new Animal();
//通过多态的方式
Animal a = new Cat();
a.eat();
}
}
(1) 抽象类的成员特点
/*
抽象类的成员特点:
成员变量:既可以是变量,也可以是常量。
构造方法:有。
用于子类访问父类数据的初始化。
成员方法:既可以是抽象的,也可以是非抽象的。

抽象类的成员方法特性:
	A:抽象方法 强制要求子类做的事情。
	B:非抽象方法 子类继承的事情,提高代码复用性。

*/
abstract class Animal {
public int num = 10;
public final int num2 = 20;

public Animal() {}

public Animal(String name,int age){}

public abstract void show();

public void method() {
	System.out.println("method");
}

}

class Dog extends Animal {
public void show() {
System.out.println(“show Dog”);
}
}

class AbstractDemo2 {
public static void main(String[] args) {
//创建对象
Animal a = new Dog();
a.num = 100;
System.out.println(a.num);
//a.num2 = 200;
System.out.println(a.num2);
System.out.println("--------------");
a.show();
a.method();
}
}

(2) 抽象类的练习题
/*
假如我们在开发一个系统时需要对员工类进行设计,员工包含3个属性:姓名、工号以及工资。
经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。
请使用继承的思想设计出员工类和经理类。要求类中提供必要的方法进行属性访问。

分析:
	普通员工类
		成员变量:姓名、工号以及工资。
		成员方法:工作
	经理类:
		成员变量:姓名、工号以及工资,奖金属性
		成员方法:工作
		
实现:
	员工类:
	普通员工类:
	经理类:

*/
//定义员工类
abstract class Employee {
//姓名、工号以及工资
private String name;
private String id;
private int salary;

public Employee() {}

public Employee(String name,String id,int salary) {
	this.name = name;
	this.id = id;
	this.salary = salary;
}

public String getName() {
	return name;
}

public void setName(String name) {
	this.name = name;
}

public String getId() {
	return id;
}

public void setId(String id) {
	this.id = id;
}

public int getSalary() {
	return salary;
}

public void setSalary(int salary) {
	this.salary = salary;
}

//工作
public abstract void work();

}

//普通员工类
class Programmer extends Employee {
public Programmer(){}

public Programmer(String name,String id,int salary) {
	super(name,id,salary);
}

public void work() {
	System.out.println("按照需求写代码");
}

}

//经理类
class Manager extends Employee {
//奖金
private int money; //bonus 奖金

public Manager(){}

public Manager(String name,String id,int salary,int money) {
	super(name,id,salary);
	this.money = money;
}

public void work() {
	System.out.println("跟客户谈需求");
}

public int getMoney() {
	return money;
}

public void setMoney(int money) {
	this.money = money;
}

}

class AbstractTest4 {
public static void main(String[] args) {
//测试普通员工
Employee emp = new Programmer();
emp.setName(“林青霞”); // 多态中成员访问特点
emp.setId(“czbk001”); // C:成员方法 编译看左边,运行看左边。(父类自己的成员方法)
emp.setSalary(18000);
System.out.println(emp.getName()+"—"+emp.getId()+"—"+emp.getSalary());
emp.work(); // 编译看左边,运行看右边。(重写的成员方法)
System.out.println("-------------");
emp = new Programmer(“林青霞”,“czbk001”,18000);
System.out.println(emp.getName()+"—"+emp.getId()+"—"+emp.getSalary());
emp.work();
System.out.println("-------------");

	/*
	emp = new Manager();
	emp.setName("刘意");
	emp.setId("czbk002");
	emp.setSalary(8000);
	emp.setMoney(2000);
	*/
	//由于子类有特有的内容,所以我们用子类来测试
	Manager m = new Manager();
	m.setName("刘意");
	m.setId("czbk002");
	m.setSalary(8000);
	m.setMoney(2000);
	System.out.println(m.getName()+"---"+m.getId()+"---"+m.getSalary()+"---"+m.getMoney());
	m.work();
	System.out.println("-------------");
	
	//通过构造方法赋值
	m = new Manager("刘意","czbk002",8000,2000);
	System.out.println(m.getName()+"---"+m.getId()+"---"+m.getSalary()+"---"+m.getMoney());
	m.work();
}

(3) 抽象类中的小问题
*
一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
A:可以。
B:不让创建对象。

abstract不能和哪些关键字共存?
private 冲突
final 冲突
static 无意义
*/
abstract class Fu {
//public abstract void show();
//非法的修饰符组合: abstract和private
//private abstract void show();

//非法的修饰符组合
//final abstract void show();	

//非法的修饰符组合
static abstract void show();

public static void method() {
	System.out.println("method");
}

}

class Zi extends Fu {
public void show() {}
}

class AbstractDemo3 {
public static void main(String[] args) {
Fu.method();
}
}

接口
Java中就提供了接口来定义这些额外功能,并不给出具体实现,将来哪些猫狗需要被培训,只需要这部分猫狗把这些额外功能实现即可。
(1)接口的特点:
A:接口用关键字interface表示
interface 接口名 {}
B:类实现接口用implements表示
class 类名 implements 接口名 {}
C:接口不能实例化
那么,接口如何实例化呢?
按照多态的方式来实例化。
D:接口的子类
a:可以是抽象类。但是意义不大。
b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)

由此可见:
	A:具体类多态(几乎没有)
	B:抽象类多态(常用)
	C:接口多态(最常用)

//定义动物培训接口
interface AnimalTrain {
public abstract void jump();
}

//抽象类实现接口
abstract class Dog implements AnimalTrain {
}

//具体类实现接口
class Cat implements AnimalTrain {
public void jump() {
System.out.println(“猫可以跳高了”);
}
}

class InterfaceDemo {
public static void main(String[] args) {
//AnimalTrain是抽象的; 无法实例化
//AnimalTrain at = new AnimalTrain();
//at.jump();

	AnimalTrain at = new Cat();
	at.jump();
}

}

(2)接口成员特点

 成员变量;只能是常量,并且是静态的。
			默认修饰符:public static final
			建议:自己手动给出。
	构造方法:接口没有构造方法。
	成员方法:只能是抽象方法。
			默认修饰符:public abstract
			建议:自己手动给出。
	
所有的类都默认继承自一个类:Object。
类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。

interface Inter {
public int num = 10;
public final int num2 = 20;
public static final int num3 = 30;

//错误: 需要<标识符>
//public Inter() {}

//接口方法不能带有主体
//public void show() {}

//abstract void show(); //默认public
public void show(); //默认abstract

}

//接口名+Impl这种格式是接口的实现类格式
/*
class InterImpl implements Inter {
public InterImpl() {
super();
}
}
*/

class InterImpl extends Object implements Inter {
public InterImpl() {
super();
}

public void show() {}

}

//测试类
class InterfaceDemo2 {
public static void main(String[] args) {
//创建对象
Inter i = new InterImpl();
System.out.println(i.num);
System.out.println(i.num2);
//i.num = 100;
//i.num2 = 200;
//System.out.println(i.num); //无法为最终变量num分配值
//System.out.println(i.num2);//无法为最终变量num2分配值
System.out.println(Inter.num);
System.out.println(Inter.num2);
System.out.println("--------------");
}
(3)类与类,类与接口,接口与接口的关系
/*
类与类:
继承关系,只能单继承,可以多层继承。
类与接口:
实现关系,可以单实现,也可以多实现。
并且还可以在继承一个类的同时实现多个接口。
接口与接口:
继承关系,可以单继承,也可以多继承。
*/
interface Father {
public abstract void show();
}

interface Mother {
public abstract void show2();
}

interface Sister extends Father,Mother {

}

//class Son implements Father,Mother //多实现
class Son extends Object implements Father,Mother {
public void show() {
System.out.println(“show son”);
}

public void show2() {
	System.out.println("show2 son");
}

}

class InterfaceDemo3 {
public static void main(String[] args) {
//创建对象
Father f = new Son();
f.show();
//f.show2(); //报错

	Mother m = new Son();
	//m.show(); //报错
	m.show2();
}

(4)抽象类与接口的区别
A:成员区别
抽象类:
成员变量:可以变量,也可以常量
构造方法:有
成员方法:可以抽象,也可以非抽象
接口:
成员变量:只可以常量
成员方法:只可以抽象

B:关系区别
类与类
继承,单继承
类与接口
实现,单实现,多实现
接口与接口
继承,单继承,多继承

C:设计理念区别
抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。
接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。

(5) 例题
//定义抽烟接口
interface Smoking {
//抽烟的抽象方法
public abstract void smoke();
}

//定义抽象人类
abstract class Person {
//姓名
private String name;
//年龄
private int age;

public Person() {}

public Person(String name,int age) {
	this.name = name;
	this.age = 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 abstract void eat();

//睡觉(){}
public void sleep() {
	System.out.println("睡觉觉了");
}

}

//具体老师类
class Teacher extends Person {
public Teacher() {}

public Teacher(String name,int age) {
	super(name,age);
}

public void eat() {
	System.out.println("吃大白菜");
}

}

//具体学生类
class Student extends Person {
public Student() {}

public Student(String name,int age) {
	super(name,age);
}

public void eat() {
	System.out.println("吃红烧肉");
}

}

//抽烟的老师
class SmokingTeacher extends Teacher implements Smoking {
public SmokingTeacher() {}

public SmokingTeacher(String name,int age) {
	super(name,age);
}

public void smoke() {
	System.out.println("抽烟的老师");
}

}

//抽烟的学生
class SmokingStudent extends Student implements Smoking {
public SmokingStudent() {}

public SmokingStudent(String name,int age) {
	super(name,age);
}

public void smoke() {
	System.out.println("抽烟的学生");
}

}

class InterfaceTest2 {
public static void main(String[] args) {
//测试学生
SmokingStudent ss = new SmokingStudent();
ss.setName(“林青霞”);
ss.setAge(27);
System.out.println(ss.getName()+"—"+ss.getAge());
ss.eat();
ss.sleep();
ss.smoke();
System.out.println("-------------------");

	SmokingStudent ss2 = new SmokingStudent("刘意",30);
	System.out.println(ss2.getName()+"---"+ss2.getAge());
	ss2.eat();
	ss2.sleep();
	ss2.smoke();
	
	
}

}

第五部分

  1. 形式参数
    (1) 基本类型(太简单,不是我今天要讲解的)
    引用类型
    类名:
    抽象类:
    接口

(2) 引用类型为类名

类名:(匿名对象的时候其实我们已经讲过了) 需要的是该类的对象
//需求2:我要测试StudentDemo类中的method()方法
StudentDemo sd = new StudentDemo();
Student ss = new Student();
sd.method(ss);
System.out.println("----------------");

	//匿名对象用法
	new StudentDemo().method(new Student());

(3) 引用类型为抽象类

    抽象类:需要的是该抽象的类子类对象

abstract class Person {
public abstract void study();
}

class PersonDemo {
public void method(Person p) {//p; p = new Student(); Person p = new Student(); //多态
p.study();
}
}

//定义一个具体的学生类
class Student extends Person {
public void study() {
System.out.println(“Good Good Study,Day Day Up”);
}
}

class PersonTest {
public static void main(String[] args) {
//目前是没有办法的使用的
//因为抽象类没有对应的具体类
//那么,我们就应该先定义一个具体类
//需求:我要使用PersonDemo类中的method()方法
PersonDemo pd = new PersonDemo();
Person p = new Student();
pd.method§;
}
}

(4) 引用类型为接口
接口:需要的是该接口的实现类对象
//定义一个爱好的接口
interface Love {
public abstract void love();
}

class LoveDemo {
public void method(Love l) { //l; l = new Teacher(); Love l = new Teacher(); 多态
l.love();
}
}

//定义具体类实现接口
class Teacher implements Love {
public void love() {
System.out.println(“老师爱学生,爱Java,爱林青霞”);
}
}

class TeacherTest {
public static void main(String[] args) {
//需求:我要测试LoveDemo类中的love()方法
LoveDemo ld = new LoveDemo();
Love l = new Teacher();
ld.method(l);
}
}

  1. 返回值类型
    (1) 基本类型(太简单)
    (2) 引用类型
  2. 类:返回的是该类的对象
    class Student {
    public void study() {
    System.out.println(“Good Good Study,Day Day Up”);
    }
    }

class StudentDemo {
public void method(Student s) { //ss; ss = new Student(); Student s = new Student();
s.study();
}
}

class StudentTest {
public static void main(String[] args) {
//需求:我要测试Student类的study()方法
Student s = new Student();
s.study();
System.out.println("----------------");

	//需求2:我要测试StudentDemo类中的method()方法
	StudentDemo sd = new StudentDemo();
	Student ss = new Student();
	sd.method(ss);
	System.out.println("----------------");
	
	//匿名对象用法
	new StudentDemo().method(new Student());
}

}

  1. 抽象类:返回的是该抽象类的子类对象

abstract class Person {
public abstract void study();
}

class PersonDemo {
public Person getPerson() {
//Person p = new Student();
//return p;

	return new Student();
}

}

class Student extends Person {
public void study() {
System.out.println(“Good Good Study,Day Day Up”);
}
}

class PersonTest2 {
public static void main(String[] args) {
//需求:我要测试Person类中的study()方法
PersonDemo pd = new PersonDemo();
Person p = pd.getPerson(); //new Student(); Person p = new Student(); 多态
p.study();
}
}

  1. 接口: 返回的是该接口的实现类的对象

//定义一个爱好的接口
interface Love {
public abstract void love();
}

class LoveDemo {
public Love getLove() {
//Love l = new Teacher();
//return l;

	return new Teacher();
}

}

//定义具体类实现接口
class Teacher implements Love {
public void love() {
System.out.println(“老师爱学生,爱Java,爱林青霞”);
}
}

class TeacherTest2 {
public static void main(String[] args) {
//如何测试呢?
LoveDemo ld = new LoveDemo();
Love l = ld.getLove(); //new Teacher(); Love l = new Teacher(); 多态
l.love();
}
}

  1. 链式编程
    每次调用完毕方法后,返回的是一个对象。
    class Student {
    public void study() {
    System.out.println(“Good Good Study,Day Day Up”);
    }
    }

class StudentDemo {
public Student getStudent() {
return new Student();
}
}

class StudentTest3 {
public static void main(String[] args) {
//如何调用的呢?
StudentDemo sd = new StudentDemo();
//Student s = sd.getStudent();
//s.study();

	//大家注意了
	sd.getStudent().study();
}

}

  1. Package关键字(包),inport关键字(导包)
    包:
    A:其实就是文件夹
    B:作用
    a:把相同的类名放到不同的包中
    b:对类进行分类管理

    举例:
    学生:增加,删除,修改,查询
    老师:增加,删除,修改,查询

    方案1:按照功能分
    	cn.itcast.add
    		AddStudent
    		AddTeacher
    	cn.itcast.delete
    		DeleteStudent
    		DeleteTeacher
    	cn.itcast.update
    		UpdateStudent
    		UpdateTeacher
    	cn.itcast.find
    		FindStudent
    		FindTeacher
    
    方案2:按照模块分
    	cn.itcast.teacher
    		AddTeacher
    		DeleteTeacher
    		UpdateTeacher
    		FindTeacher
    	cn.itcast.student
    		AddStudent
    		DeleteStudent
    		UpdateStudent
    		FindStudent		
    

    包的定义
    package 包名;
    多级包用.分开即可

    注意事项:
    A:package语句必须是程序的第一条可执行的代码
    B:package语句在一个java文件中只能有一个
    C:如果没有package,默认表示无包名

    带包的编译和运行:
    A:手动式
    a:编写一个带包的java文件。
    b:通过javac命令编译该java文件。
    c:手动创建包名。
    d:把b步骤的class文件放到c步骤的最底层包
    e:回到和包根目录在同一目录的地方,然后运行
    带包运行。

    B:自动式
    	a:编写一个带包的java文件。
    	b:javac编译的时候带上-d即可
    		javac -d . HelloWorld.java
    	c:回到和包根目录在同一目录的地方,然后运行
    		带包运行。
    

    导包:
    格式:import 包名;
    这种方式导入是到类的名称。
    注意:我们用谁就导谁。

    面试题:
    package,import,class有没有顺序关系?
    有。
    package > import > class

    Package:只能有一个
    import:可以有多个
    class:可以有多个,以后建议是一个
    
  2. 四种权限修饰符

(1) 权限修饰符

				本类	同一个包下	不同包下的子类	不同包下的无关类
	private		Y
	默认		Y		Y
	protected	Y		Y			Y
	public		Y		Y			Y				Y

(2) 这四种权限修饰符在任意时刻只能出现一种。
public class Demo {}

  1. 常见的修饰符

    修饰符:
    权限修饰符:private,默认的,protected,public
    状态修饰符:static,final
    抽象修饰符:abstract

    类:
    权限修饰符:默认修饰符,public
    状态修饰符:final
    抽象修饰符:abstract

    用的最多的就是:public
    

    成员变量:
    权限修饰符:private,默认的,protected,public
    状态修饰符:static,final

    用的最多的就是:private
    

    构造方法:
    权限修饰符:private,默认的,protected,public

    用的最多的就是:public
    

    成员方法:
    权限修饰符:private,默认的,protected,public
    状态修饰符:static,final
    抽象修饰符:abstract

    用的最多的就是:public
    

    除此以外的组合规则:
    成员变量:public static final
    成员方法:public static
    public abstract
    public final

内部类

(1)内部类概述:
把类定义在其他类的内部,这个类就被称为内部类。
举例:在类A中定义了一个类B,类B就是内部类。

内部的访问特点:
	A:内部类可以直接访问外部类的成员,包括私有。
	B:外部类要访问内部类的成员,必须创建对象。

*/
class Outer {
private int num = 10;

class Inner {
	public void show() {
		System.out.println(num);
	}
}

public void method() {
	//找不到符号
	//show();

	Inner i = new Inner();
	i.show();
}

}

class InnerClassDemo {
public static void main(String[] args) {

}

}

(2)内部类的位置
按照内部类在类中定义的位置不同,可以分为如下两种格式: 成员位置(成员内部类) 局部位置(局部内部类)

  1. 成员内部类:

    (1)如何直接访问内部类的成员。
    外部类名.内部类名 对象名 = 外部类对象.内部类对象;
    

*/
class Outer {
private int num = 10;

class Inner {
	public void show() {
		System.out.println(num);
	}
}

}

class InnerClassDemo3 {
public static void main(String[] args) {
//需求:我要访问Inner类的show()方法
//Inner i = new Inner();
//i.show();

	//格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
	Outer.Inner oi = new Outer().new Inner();
	oi.show();
}

}

(2)成员内部类的修饰符:
private 为了保证数据的安全性
static 为了方便访问数据
注意:静态内部类访问的外部类数据必须用静态修饰。

内部类被静态修饰后的方法 静态方法 非静态方法
案例:我有一个人(人有身体,身体内有心脏。)

	class Body {
		private class Heart {
			public void operator() {
				System.out.println("心脏搭桥");
			}
		}
		
		public void method() {
			if(如果你是外科医生) {
				Heart h = new Heart();
				h.operator();
			}
		}
	}
	
	按照我们刚才的讲解,来使用一下
	Body.Heart bh = new Body().new Heart();
	bh.operator();
	//加了private后,就不能被访问了,那么,怎么玩呢?
	Body b =  new Body();
	b.method();

*/
class Outer {
private int num = 10;
private static int num2 = 100;

//内部类用静态修饰是因为内部类可以看出是外部类的成员
public static class Inner {
	public void show() {
		//System.out.println(num);
		System.out.println(num2);
	}

	public static void show2() {
		//System.out.println(num);
		System.out.println(num2);
	}		
}

}

class InnerClassDemo4 {
public static void main(String[] args) {
//使用内部类
// 限定的新静态类
//Outer.Inner oi = new Outer().new Inner();
//oi.show();
//oi.show2();

	//成员内部类被静态修饰后的访问方式是:
	//格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
	Outer.Inner oi = new Outer.Inner();
	oi.show();
	oi.show2();
	
	//show2()的另一种调用方式
	Outer.Inner.show2();
}

}

(3)成员内部类的面试题:
/*
面试题:
要求请填空分别输出30,20,10。

注意:
	1:内部类和外部类没有继承关系。
	2:通过外部类名限定this对象
		Outer.this

*/
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(num);
System.out.println(this.num);
//System.out.println(new Outer().num);
System.out.println(Outer.this.num);
}
}
}
class InnerClassTest {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}

2.局部内部类
A:可以直接访问外部类的成员
B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能

面试题:
	局部内部类访问局部变量的注意事项?
	A:局部内部类访问局部变量必须用final修饰
	B:为什么呢?
		局部变量是随着方法的调用而调用,随着调用完毕而消失。
		而堆内存的内容并不会立即消失。所以,我们加final修饰。
		加入final修饰后,这个变量就成了常量。既然是常量。你消失了。
		我在内存中存储的是数据20,所以,我还是有数据在使用。

class Outer {
private int num = 10;

public void method() {
	//int num2 = 20;
	final int num2 = 20;
	class Inner {
		public void show() {
			System.out.println(num);
			//从内部类中访问本地变量num2; 需要被声明为最终类型
			System.out.println(num2);//20
		}
	}
	
	//System.out.println(num2);
	
	Inner i = new Inner();
	i.show();
}

}

class InnerClassDemo5 {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}

匿名内部类

(1) 匿名内部类
就是内部类的简化写法。

前提:存在一个类或者接口
	这里的类可以是具体类也可以是抽象类。

格式:
	new 类名或者接口名(){
		重写方法;
	}
	
本质是什么呢?
	是一个继承了该类或者实现了该接口的子类匿名对象。

interface Inter {
public abstract void show();
public abstract void show2();
}

class Outer {
public void method() {
//一个方法的时候
/*
new Inter() {
public void show() {
System.out.println(“show”);
}
}.show();
*/

	//二个方法的时候
	/*
	new Inter() {
		public void show() {
			System.out.println("show");
		}
		
		public void show2() {
			System.out.println("show2");
		}
	}.show();
	
	new Inter() {
		public void show() {
			System.out.println("show");
		}
		
		public void show2() {
			System.out.println("show2");
		}
	}.show2();
	*/
	
	//如果我是很多个方法,就很麻烦了
	//那么,我们有没有改进的方案呢?
	Inter i = new Inter() { //多态
		public void show() {
			System.out.println("show");
		}
		
		public void show2() {
			System.out.println("show2");
		}
	};
	
	i.show();
	i.show2();
}

}

class InnerClassDemo6 {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}

(2)匿名内部类在开发中的使用:

interface Person {
public abstract void study();
}

class PersonDemo {
//接口名作为形式参数
//其实这里需要的不是接口,而是该接口的实现类的对象
public void method(Person p) {
p.study();
}
}

//实现类
class Student implements Person {
public void study() {
System.out.println(“好好学习,天天向上”);
}
}

class InnerClassTest2 {
public static void main(String[] args) {
//测试
PersonDemo pd = new PersonDemo();
Person p = new Student();
pd.method§;
System.out.println("--------------------");

	//匿名内部类在开发中的使用
	//匿名内部类的本质是继承类或者实现了接口的子类匿名对象
	pd.method(new Person(){
		public void study() {
			System.out.println("好好学习,天天向上");
		}
	});
}

}
输出结果: 好好学习,天天向上
--------------------
好好学习,天天向上

(3)匿名内部类面试题:
按照要求,补齐代码
interface Inter { void show(); }
class Outer { //补齐代码 }
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”
*/
interface Inter {
void show();
//public abstract
}

class Outer {
//补齐代码
public static Inter method() {
//子类对象 – 子类匿名对象
return new Inter() {
public void show() {
System.out.println(“HelloWorld”);
}
};
}
}

class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
/*
1:Outer.method()可以看出method()应该是Outer中的一个静态方法。
2:Outer.method().show()可以看出method()方法的返回值是一个对象。
又由于接口Inter中有一个show()方法,所以我认为method()方法的返回值类型是一个接口。
*/
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值