java面向对象

成员变量和局部变量的区别:

A:在类中的位置不同

成员变量:在类中方法外

局部变量:在方法定义中或者方法声明上

B:在内存中的位置不同

成员变量:在堆内存

局部变量:在栈内存

C:生命周期不同

成员变量:随着对象的创建而存在,随着对象的消失而消失

局部变量:随着方法的调用而存在,随着方法的调用完毕而消失

D:初始化值不同

成员变量:有默认初始化值

局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。

   

注意事项:

局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。

   

demo:

class Varialbe {

//成员变量

//int num = 10;

int num; //0

   

public void show() {

//int num2 = 20; //局部变量

//可能尚未初始化变量num2

//int num2; //没有默认值

int num2 = 20;

System.out.println(num2);

   

//int num = 100;

System.out.println(num);

}

}

   

   

class VariableDemo {

public static void main(String[] args) {

Varialbe v = new Varialbe();

   

System.out.println(v.num); //访问成员变量

   

v.show();        

   

}

}

形式参数是类名:

基本类型:形式参数的改变不影响实际参数

引用类型:形式参数的改变直接影响实际参数

//形式参数是基本类型

class Demo {

public int sum(int a,int b) {

return a + b;

}

}

   

//形式参数是引用类型

class Student {

public void show() {

System.out.println("我爱学习");

}

}

   

class StudentDemo {

//如果你看到了一个方法的形式参数是一个类类型(引用类型),这里其实需要的是该类的对象。

public void method(Student s) { //调用的时候,把main方法中的s的地址传递到了这里 Student s = new Student();

s.show();

}

}

   

class ArgsTest {

public static void main(String[] args) {

//形式参数是基本类型的调用

Demo d = new Demo();

int result = d.sum(10,20);

System.out.println("result:"+result);

System.out.println("--------------");

   

//形式参数是引用类型的调用

//需求:我要调用StudentDemo类中的method()方法

StudentDemo sd = new StudentDemo();

//创建学生对象

Student s = new Student();

sd.method(s); //把s的地址给到了这里

}

}

匿名对象:

就是没有名字的对象

匿名对象的应用场景:

A:调用方法,仅仅只调用一次的时候。

注意:调用多次的时候,不适合。

那么,这种匿名调用有什么好处吗?

有,匿名对象调用完毕就是垃圾。可以被垃圾回收器回收。

B:匿名对象可以作为实际参数传递

demo:

class Student {

public void show() {

System.out.println("我爱学习");

}

}

   

class StudentDemo {

public void method(Student s) {

s.show();

}

}

   

class NoNameDemo {

public static void main(String[] args) {

//带名字的调用

Student s = new Student();

s.show();

s.show();

System.out.println("--------------");

   

//匿名对象

//new Student();

//匿名对象调用方法

new Student().show();

new Student().show(); //这里其实是重新创建了一个新的对象

System.out.println("--------------");

   

   

//匿名对象作为实际参数传递

StudentDemo sd = new StudentDemo();

//Student ss = new Student();

//sd.method(ss); //这里的s是一个实际参数

//匿名对象

sd.method(new Student());

   

//在来一个

new StudentDemo().method(new Student());

        }

}

封装的概述:

是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

好处:

隐藏实现细节,提供公共的访问方式

提高了代码的复用性

提高安全性。

封装原则:

将不需要对外提供的内容都隐藏起来。

把属性隐藏,提供公共方法对其访问。

   

demo:

定义一个学生类:

成员变量:nameage

成员方法:show()方法

   

我们在使用这个案例的过程中,发现了一个问题:

通过对象去给成员变量赋值,可以赋值一些非法的数据。

这是不合理的。

应该是这个样子的:在赋值之前,先对数据进行判断。

判断到底在哪里做比较合适呢?

StudentDemo类是一个测试类,测试类一般只创建对象,调用方法。        

所以,这个判断应该定义在Student类中。

而我们在成员变量的位置可不可以进行数据判断呢?

是不可以的,因为做数据校验,必须要依靠一些逻辑语句。

逻辑语句是应该定义在方法中的,所以,我们最终决定在Student类中提供一个方法

来对数据进行校验。

   

按照我们前面的分析,我们给出了一个方法进行校验。

但是呢,它偏偏不调用方法来赋值,还是直接赋值了,

这样我们的方法就没有起到作用。

我就应该要求你必须使用我的方法,而不能直接调用成员变量赋值。

怎么去强制要求不能直接使用成员变量呢?

针对这种情况,Java就提供了一个关键字 private

   

private:私有的。可以修饰成员变量和成员方法。

注意:被private修饰的成员只能在本类中访问。

  

class Student {

//姓名

String name;

//年龄

private int age;

   

//写一个方法对数据进行校验

/*

返回值类型:void

参数列表:int a

*/

public void setAge(int a) {

if(a < 0 || age > 120) {

System.out.println("你给的年龄有问题");

}else {

age = a;

}

}

   

   

//show()方法,显示所有成员变量值

public void show() {

System.out.println("姓名:"+name);

System.out.println("年龄:"+age);

}

}

   

class StudentDemo {

public static void main(String[] args) {

//创建学生对象

Student s = new Student();

s.show();

System.out.println("--------------");

   

//给成员变量赋值

s.name = "林青霞";

//s.age = 27;

s.setAge(27);

s.show();

System.out.println("--------------");

   

//age赋值

//s.age = -27; //这个数据是不合理的

//通过方法给值

s.setAge(-27);

s.show();

System.out.println("--------------");

}

}

   

private关键字:

是一个权限修饰符。

可以修饰成员(成员变量和成员方法)

被private修饰的成员只在本类中才能访问。

   

private最常见的应用:

把成员变量用private修饰

提供对应的getXxx()/setXxx()方法

demo:

封装和private的应用:

A:把成员变量用private修饰

B:提高对应的getXxx()setXxx()方法

  

//定义学生类

class Student {

//姓名

private String name;

//年龄

private int age;

   

//姓名获取值

public String getName() {

return name;

}

   

//姓名设置值

public void setName(String n) {

name = n;

}

   

//年龄获取值

public int getAge() {

return age;

}

   

//年龄赋值

public void setAge(int a) {

age = a;

}

}

   

//测试类

class StudentTest {

public static void main(String[] args) {

//创建学生对象

Student s = new Student();

   

//使用成员变量

//错误:被私有修饰了,外界不能直接访问了

//System.out.println(s.name+"---"+s.age);

System.out.println(s.getName()+"---"+s.getAge());

   

//给成员变量赋值

//s.name = "林青霞";

//s.age = 27;

//通过方法给赋值

s.setName("林青霞");

s.setAge(27);

System.out.println(s.getName()+"---"+s.getAge());

}

}

this关键字:

this:是当前类的对象引用。简单的记,它就代表当前类的一个对象。

   

注意:谁调用这个方法,在该方法内部的this就代表谁。

   

this的场景:

解决局部变量隐藏成员变量

Demo:

//定义学生类

class Student {

//姓名

private String name;

//年龄

private int age;

   

//姓名获取值

public String getName() {

return name;

}

   

//姓名设置值

public void setName(String name) { //name = "林青霞";

//name = name; //变量的使用规则:就近原则

//这里是类名,目前还没有说过类似的用法,所以这个是有问题的

//这里的调用只能通过对象名

//这个对象如果存在,它应该代表的是Student的一个对象。

//那么,谁能够代表当前类的对象呢? java就提供了一个关键字 this

//Student.name = name;

this.name = name;

}

   

//年龄获取值

public int getAge() {

return age;

}

   

//年龄赋值

public void setAge(int age) {

this.age = age;

}

}

   

//测试类

class StudentTest {

public static void main(String[] args) {

//创建学生对象

Student s = new Student();

   

//给成员变量赋值

s.setName("林青霞");

s.setAge(27);

//获取数据

System.out.println(s.getName()+"---"+s.getAge());

}

}

   

   

构造方法概述和格式:

A:如果我们没有给出构造方法,系统将自动提供一个无参构造方法。

B:如果我们给出了构造方法,系统将不再提供默认的无参构造方法。

注意:这个时候,如果我们还想使用无参构造方法,就必须自己给出。建议永远自己给出无参构造方法

   

给成员变量赋值有两种方式:

A:setXxx()

B:构造方法

demo:

class Student {

private String name;

private int age;

   

public Student() {

//System.out.println("我给了,你还给不");

System.out.println("这是无参构造方法");

}

   

//构造方法的重载格式

public Student(String name) {

System.out.println("这是带一个String类型的构造方法");

this.name = name;

}

   

public Student(int age) {

System.out.println("这是带一个int类型的构造方法");

this.age = age;

}

   

public Student(String name,int age) {

System.out.println("这是一个带多个参数的构造方法");

this.name = name;

this.age = age;

}

   

public void show() {

System.out.println(name+"---"+age);

}

}

   

class ConstructDemo2 {

public static void main(String[] args) {

//创建对象

Student s = new Student();

s.show();

System.out.println("-------------");

   

//创建对象2

Student s2 = new Student("林青霞");

s2.show();

System.out.println("-------------");

   

//创建对象3

Student s3 = new Student(27);

s3.show();

System.out.println("-------------");

   

//创建对象4

Student s4 = new Student("林青霞",27);

s4.show();

}

}

类初始化的过程:

static关键字:

static的特点:(它可以修饰成员变量,还可以修饰成员方法)

A:随着类的加载而加载

回想main方法。

B:优先于对象存在

C:被类的所有对象共享

举例:咱们班级的学生应该共用同一个班级编号。

其实这个特点也是在告诉我们什么时候使用静态?

如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的。

举例:

饮水机(用静态修饰)

水杯(不能用静态修饰)

D:可以通过类名调用

其实它本身也可以通过对象名调用。

推荐使用类名调用。

   

静态修饰的内容一般我们称其为:与类相关的,类成员

demo:

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();

}

}

main方法的格式详解:

main方法的格式讲解:

public static void main(String[] args) {...}

   

public:公共的,访问权限是最大的。由于main方法是被jvm调用,所以权限要够大。

static:静态的,不需要创建对象,通过类名就可以。方便jvm的调用。

void:因为我们曾经说过,方法的返回值是返回给调用者,而main方法是被jvm调用。你返回内容给jvm没有意义。

main:是一个常见的方法入口。我见过的语言都是以main作为入口。

String[] args:这是一个字符串数组。值去哪里了?

这个东西到底有什么用啊?怎么给值啊?

这个东西早期是为了接收键盘录入的数据的。

格式是:

java MainDemo hello world java

demo:

class MainDemo {

public static void main(String[] args) {

//System.out.println(args); //[Ljava.lang.String;@175078b

//System.out.println(args.length); //0

//System.out.println(args[0]); //ArrayIndexOutOfBoundsException

   

//接收数据后

System.out.println(args);

System.out.println(args.length);

//System.out.println(args[0]);

for(int x=0; x<args.length; x++) {

System.out.println(args[x]);

}

}

}

帮助文档的制作和使用:

如何制作一个说明书呢?

A:写一个工具类

B:对这个类加入文档注释

怎么加呢?

加些什么东西呢?

C:用工具解析文档注释

javadoc工具

D:格式

javadoc -d 目录 -author -version ArrayTool.java

   

目录:就可以写一个文件夹的路径

   

制作帮助文档出错:

找不到可以文档化的公共或受保护的类:告诉我们类的权限不够

帮助文档的使用:

1:打开帮助文档

2:点击显示,找到索引,看到输入框

3:知道你要找谁?以Scanner举例

4:在输入框里面输入Scanner,然后回车

5:看包

java.lang包下的类不需要导入,其他的全部需要导入。

   

要导入:

java.util.Scanner

6:再简单的看看类的解释和说明,别忘了看看该类的版本

7:看类的结构

成员变量        字段摘要         

构造方法        构造方法摘要

成员方法         方法摘要

8:学习构造方法        

A:有构造方法        就创建对象

B:没有构造方法        成员可能都是静态的

9:看成员方法

A:左边

是否静态:如果静态,可以通过类名调用

返回值类型:人家返回什么,你就用什么接收。

B:右边

看方法名:方法名称不要写错

参数列表:人家要什么,你就给什么;人家要几个,你就给几个

获取1100之间的随机数

class MathDemo {

public static void main(String[] args) {

//获取一个随机数

//double d = Math.random();

//System.out.println(d);

   

//需求:我要获取一个1-100之间的随机数,肿么办?

for(int x=0; x<100; x++) {

int number = (int)(Math.random()*100)+1;

System.out.println(number);

}

}

}

java中的Math类:

demo:

猜数字小游戏(数据在1-100之间)

分析:

A:程序产生一个随机数。(被猜的)

B:键盘录入数据。(你猜的)

C:把你猜的和被猜的进行比较

a:大了

b:小了

c:猜中了

D:给出多次猜的机会,猜中就结束。

while()循环,猜中就break

  

class GuessNumber {

public static void main(String[] args) {

//程序产生一个随机数。(被猜的)

int number = (int)(Math.random()*100)+1;

//System.out.println(number);

   

//给出多次猜的机会,猜中就结束。

while(true) {

//键盘录入数据。(你猜的)

Scanner sc = new Scanner(System.in);

System.out.println("请输入你要猜的数据(1-100):");

int guessNumber = sc.nextInt();

   

//把你猜的和被猜的进行比较

if(guessNumber > number) {

System.out.println("你猜的数据"+guessNumber+"大了");

}else if(guessNumber < number) {

System.out.println("你猜的数据"+guessNumber+"小了");

}else {

System.out.println("恭喜你,猜中了");

break;

}

}

}

}

代码块:

在Java中,使用{}括起来的代码被称为代码块

代码块:在Java中,使用{}括起来的代码被称为代码块。

根据其位置和声明的不同,可以分为

局部代码块:局部位置,用于限定变量的生命周期。

构造代码块:在类中的成员位置,用{}括起来的代码。每次调用构造方法执行前,都会先执行构造代码块。

作用:可以把多个构造方法中的共同代码放到一起,对对象进行初始化。

静态代码块:在类中的成员位置,用{}括起来的代码,只不过它用static修饰了。

作用:一般是对类进行初始化。

demo:

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);

}

}

/*

写程序的执行结果。

   

我很伤心

我是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("我很伤心");

}

   

public static void main(String[] args) {

System.out.println("我是main方法");

   

Student s1 = new Student();

Student s2 = new Student();

}

}

java中的继承:

继承概述:

把多个类中相同的内容给提取出来定义到一个类中。

   

如何实现继承呢?        

Java提供了关键字:extends

   

格式:

class 子类名 extends 父类名 {}

   

好处:

A:提高了代码的复用性

B:提高了代码的维护性

C:让类与类之间产生了关系,是多态的前提

   

类与类产生了关系,其实也是继承的一个弊端:

类的耦合性增强了。

   

开发的原则:低耦合,高内聚。

耦合:类与类的关系

内聚:就是自己完成某件事情的能力

Demo:

//使用继承前

/*

class Student {

public void eat() {

System.out.println("吃饭");

}

   

public void sleep() {

System.out.println("睡觉");

}

}

   

class Teacher {

public void eat() {

System.out.println("吃饭");

}

   

public void sleep() {

System.out.println("睡觉");

}

}

*/

   

//使用继承后

class Person {

public void eat() {

System.out.println("吃饭");

}

   

public void sleep() {

System.out.println("睡觉");

}

}

   

class Student extends Person {}

   

class Teacher extends Person {}

   

class ExtendsDemo {

public static void main(String[] args) {

Student s = new Student();

s.eat();

s.sleep();

System.out.println("-------------");

   

Teacher t = new Teacher();

t.eat();

t.sleep();

}

}

Java中继承的特点:

A:Java只支持单继承,不支持多继承。

有些语言是支持多继承,格式:extends 类1,类2,...

B:Java支持多层继承(继承体系)

Demo:

class GrandFather {

public void show() {

System.out.println("我是爷爷");

}

}

   

class Father extends GrandFather {

public void method(){

System.out.println("我是老子");

}

}

   

class Son extends Father {}

   

class ExtendsDemo2 {

public static void main(String[] args) {

Son s = new Son();

s.method(); //使用父亲的

s.show(); //使用爷爷的

}

}

继承的注意事项:

A:子类只能继承父类所有非私有的成员(成员方法和成员变量)

B:子类不能继承父类的构造方法,但是可以通过super(马上讲)关键字去访问父类构造方法。

C:不要为了部分功能而去继承

class A {

public void show1(){}

public void show2(){}

}

   

class B {

public void show2(){}

public void show3(){}

}

   

//我们发现B类中出现了和A类一样的show2()方法,所以,我们就用继承来体现

class B extends A {

public void show3(){}

}

这样其实不好,因为这样你不但有了show2(),还多了show1()。

有可能show1()不是你想要的。

   

那么,我们什么时候考虑使用继承呢?

继承其实体现的是一种关系:"is a"。

Person

Student

Teacher

水果

苹果

香蕉

橘子

   

采用假设法。

如果有两个类A,B。只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。

Demo:

class Father {

private int num = 10;

public int num2 = 20;

   

//私有方法,子类不能继承

private void method() {

System.out.println(num);

System.out.println(num2);

}

   

public void show() {

System.out.println(num);

System.out.println(num2);

}

}

   

class Son extends Father {

public void function() {

//num可以在Father中访问private

//System.out.println(num); //子类不能继承父类的私有成员变量

System.out.println(num2);

}

}

   

class ExtendsDemo3 {

public static void main(String[] args) {

// 创建对象

Son s = new Son();

//s.method(); //子类不能继承父类的私有成员方法

s.show();

s.function();

}

}

继承中成员变量的关系:

类的组成:

成员变量:

构造方法:

成员方法:

而现在我们又讲解了继承,所以,我们就应该来考虑一下,类的组成部分的各自关系。

   

继承中成员变量的关系:

A:子类中的成员变量和父类中的成员变量名称不一样,这个太简单。

B:子类中的成员变量和父类中的成员变量名称一样,这个怎么玩呢?

在子类方法中访问一个变量的查找顺序:

a:在子类方法的局部范围找,有就使用

b:在子类的成员范围找,有就使用

c:在父类的成员范围找,有就使用

d:如果还找不到,就报错。

demo:

class Father {

public int num = 10;

   

public void method() {

int num = 50;

}

}

   

class Son extends Father {

public int num2 = 20;

public int num = 30;

   

public void show() {

int num = 40;

System.out.println(num);

System.out.println(num2);

// 找不到符号

System.out.println(num3);

}

}

   

class ExtendsDemo4 {

public static void main(String[] args) {

//创建对象

Son s = new Son();

s.show();

}

}

this和super的区别:

引入

问题是:

我不仅仅要输出局部范围的num,还要输出本类成员范围的num。怎么办呢?

我还想要输出父类成员范围的num。怎么办呢?

如果有一个东西和this相似,但是可以直接访问父类的数据就好了。

恭喜你,这个关键字是存在的:super

thissuper的区别?

分别是什么呢?

this代表本类对应的引用。

super代表父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)

   

怎么用呢?

A:调用成员变量

this.成员变量 调用本类的成员变量

super.成员变量 调用父类的成员变量

B:调用构造方法

this(...)        调用本类的构造方法

super(...)        调用父类的构造方法

C:调用成员方法

this.成员方法 调用本类的成员方法

super.成员方法 调用父类的成员方法

demo:

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();

}

}

继承中构造方法的关系:

A:子类中所有的构造方法默认都会访问父类中空参数的构造方法

B:为什么呢?

因为子类会继承父类中的数据,可能还会使用父类的数据。

所以,子类初始化之前,一定要先完成父类数据的初始化。

   

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

demo:

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("林青霞");

}

}

方法的重写:

子类中出现了和父类中方法的声明一模一样的方法声明,也被成为方法的覆盖,方法重写。

方法重载:

本类中出现的方法名一样,参数列表不同的方法。与返回值无关。

   

子类对象调用方法的时候:

先找子类本身,再找父类。

   

方法重写的应用:

当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。

这样,即沿袭了父类的功能,又定义了子类特有的内容。

demo:

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("林青霞");

}

}

   

方法重写的注意事项

A:父类中私有方法不能被重写

因为父类私有方法子类根本就无法继承

B:子类重写父类方法时,访问权限不能更低

最好就一致

C:父类静态方法,子类也必须通过静态方法进行重写

其实这个算不上方法重写,但是现象确实如此

demo:

class Father {

//private void show() {}

   

/*

public void show() {

System.out.println("show Father");

}

*/

   

void show() {

System.out.println("show Father");

}

/*

public static void method() {

   

}

*/

   

public void method() {

   

}

}

   

class Son extends Father {

//private void show() {}

   

/*

public void show() {

System.out.println("show Son");

}

*/

   

public void show() {

System.out.println("show Son");

}

   

   

public static void method() {

   

}

   

/*

public void method() {

   

}

*/

}

   

class ExtendsDemo10 {

public static void main(String[] args) {

Son s = new Son();

s.show();

}

}

demo:

1:方法重写和方法重载的区别?方法重载能改变返回值类型吗?

   

方法重写:

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

   

方法重载:

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

   

   

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

   

   

Override:方法重写

Overload:方法重载

  

demo:

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

   

this:代表当前类的对象引用

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

   

场景:

成员变量:

this.成员变量

super.成员变量

构造方法:

this(...)

super(...)

成员方法:

this.成员方法

  

demo:

学生案例和老师案例讲解

   

学生:

成员变量;姓名,年龄

构造方法:无参,带参

成员方法:getXxx()/setXxx()

老师:

成员变量;姓名,年龄

构造方法:无参,带参

成员方法:getXxx()/setXxx()

   

看上面两个类的成员,发现了很多相同的东西,所以我们就考虑抽取一个共性的类:

人:

成员变量;姓名,年龄

构造方法:无参,带参

成员方法:getXxx()/setXxx()

   

学生 继承 人

老师 继承 人

  

//定义人类

class Person {

//姓名

private String name;

//年龄

private int age;

   

public Person() {

}

   

public Person(String name,int age) { //"林青霞",27

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;

}

}

   

//定义学生类

class Student extends Person {

public Student() {}

   

public Student(String name,int age) { //"林青霞",27

//this.name = name;

//this.age = age;

super(name,age);

}

}

   

//定义老师类

class Teacher extends Person {

   

}

   

class ExtendsTest4 {

public static void main(String[] args) {

//创建学生对象并测试

//方式1

Student s1 = new Student();

s1.setName("林青霞");

s1.setAge(27);

System.out.println(s1.getName()+"---"+s1.getAge());

   

//方式2

Student s2 = new Student("林青霞",27);

System.out.println(s2.getName()+"---"+s2.getAge());

   

//补齐老师类中的代码并进行测试。

}

}

   

final关键字:

final关键字是最终的意思,可以修饰类,成员变量,成员方法。

修饰类,类不能被继承

修饰变量,变量就变成了常量,只能被赋值一次

修饰方法,方法不能被重写

   

常量:

A:字面值常量

"hello",10,true

B:自定义常量

final int x = 10;

   

   

demo:

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();

}

}

   

final修饰局部变量的问题

基本类型:基本类型的值不能发生改变。

引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的。

demo:

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();

}

}

   

final修饰变量的初始化时机

A:被final修饰的变量只能赋值一次。

B:在构造方法完毕前。(非静态的常量)

demo:

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);

}

}

   

多态:

多态:同一个对象(事物),在不同时刻体现出来的不同状态。

举例:

猫是猫,猫是动物。

(液体,固体,气态)

   

多态的前提:

A:要有继承关系。

B:要有方法重写。

其实没有也是可以的,但是如果没有这个就没有意义。

动物 d = new ();

d.show();

动物 d = new ();

d.show();

C:要有父类引用指向子类对象。

f = new ();

   

用代码体现一下多态。

   

多态中的成员访问特点:

A:成员变量

编译看左边,运行看左边。

B:构造方法

创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。

C:成员方法

编译看左边,运行看右边。

D:静态方法

编译看左边,运行看左边。

(静态和类相关,算不上重写,所以,访问还是左边的)

   

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

demo:

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();

}

}

多态的好处:

A:提高了代码的维护性(继承保证)

B:提高了代码的扩展性(由多态保证)

Demo:

class Animal {

public void eat(){

System.out.println("eat");

}

   

public void sleep(){

System.out.println("sleep");

}

}

   

class Dog extends Animal {

public void eat(){

System.out.println("狗吃肉");

}

   

public void sleep(){

System.out.println("狗站着睡觉");

}

}

   

class Cat extends Animal {

public void eat() {

System.out.println("猫吃鱼");

}

   

public void sleep() {

System.out.println("猫趴着睡觉");

}

}

   

class Pig extends Animal {

public void eat() {

System.out.println("猪吃白菜");

}

   

public void sleep() {

System.out.println("猪侧着睡");

}

}

   

//针对动物操作的工具类

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();

}

   

}

   

class DuoTaiDemo2 {

public static void main(String[] args) {

//我喜欢猫,就养了一只

Cat c = new Cat();

c.eat();

c.sleep();

   

//我很喜欢猫,所以,又养了一只

Cat c2 = new Cat();

c2.eat();

c2.sleep();

   

//我特别喜欢猫,又养了一只

Cat c3 = new Cat();

c3.eat();

c3.sleep();

//...

System.out.println("--------------");

//问题来了,我养了很多只猫,每次创建对象是可以接受的

//但是呢?调用方法,你不觉得很相似吗?仅仅是对象名不一样。

//我们准备用方法改进

//调用方式改进版本

//useCat(c);

//useCat(c2);

//useCat(c3);

   

//AnimalTool.useCat(c);

//AnimalTool.useCat(c2);

//AnimalTool.useCat(c3);

   

AnimalTool.useAnimal(c);

AnimalTool.useAnimal(c2);

AnimalTool.useAnimal(c3);

System.out.println("--------------");

   

//我喜欢狗

Dog d = new Dog();

Dog d2 = new Dog();

Dog d3 = new Dog();

//AnimalTool.useDog(d);

//AnimalTool.useDog(d2);

//AnimalTool.useDog(d3);

AnimalTool.useAnimal(d);

AnimalTool.useAnimal(d2);

AnimalTool.useAnimal(d3);

System.out.println("--------------");

   

//我喜欢宠物猪

//定义一个猪类,它要继承自动物,提供两个方法,并且还得在工具类中添加该类方法调用

Pig p = new Pig();

Pig p2 = new Pig();

Pig p3 = new Pig();

//AnimalTool.usePig(p);

//AnimalTool.usePig(p2);

//AnimalTool.usePig(p3);

AnimalTool.useAnimal(p);

AnimalTool.useAnimal(p2);

AnimalTool.useAnimal(p3);

System.out.println("--------------");

   

//我喜欢宠物狼,老虎,豹子...

//定义对应的类,继承自动物,提供对应的方法重写,并在工具类添加方法调用

//前面几个必须写,我是没有意见的

//但是,工具类每次都改,麻烦不

//我就想,你能不能不改了

//太简单:把所有的动物都写上。问题是名字是什么呢?到底哪些需要被加入呢?

//改用另一种解决方案。

   

}

   

/*

//调用猫的功能

public static void useCat(Cat c) {

c.eat();

c.sleep();

}

   

//调用狗的功能

public static void useDog(Dog d) {

d.eat();

d.sleep();

}

*/

}

多态的弊端:

不能使用子类的特有功能。

   

我就想使用子类的特有功能?行不行?

行。

   

怎么用呢?

A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)

B:把父类的引用强制转换为子类的引用。(向下转型)

   

对象间的转型问题:

向上转型:

Fu f = new Zi();

向下转型:

Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。

Demo:

class Fu {

public void show() {

System.out.println("show fu");

}

}

   

class Zi extends Fu {

public void show() {

System.out.println("show zi");

}

   

public void method() {

System.out.println("method 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();

}

}

多态中的继承图解:

多态中对象变化的图解:

ClassCastException:类型转换异常

一般在多态的向下转型中容易出现

多态的案例:猫狗案例:

demo:

class Animal {

public void eat(){

System.out.println("吃饭");

}

}

   

class Dog extends Animal {

public void eat() {

System.out.println("狗吃肉");

}

   

public void lookDoor() {

System.out.println("狗看门");

}

}

   

class Cat extends Animal {

public void eat() {

System.out.println("猫吃鱼");

}

   

public void playGame() {

System.out.println("猫捉迷藏");

}

}

   

class DuoTaiTest {

public static void main(String[] args) {

//定义为狗

Animal a = new Dog();

a.eat();

System.out.println("--------------");

//还原成狗

Dog d = (Dog)a;

d.eat();

d.lookDoor();

System.out.println("--------------");

//变成猫

a = new Cat();

a.eat();

System.out.println("--------------");

//还原成猫

Cat c = (Cat)a;

c.eat();

c.playGame();

System.out.println("--------------");

   

//演示错误的内容

//Dog dd = new Animal();

//Dog ddd = new Cat();

//ClassCastException

//Dog dd = (Dog)a;

}

}        

demo: 南北方人饮食文化不同的案例

class Person {

public void eat() {

System.out.println("吃饭");

}

}

   

class SouthPerson extends Person {

public void eat() {

System.out.println("炒菜,吃米饭");

}

   

public void jingShang() {

System.out.println("经商");

}

}

   

class NorthPerson extends Person {

public void eat() {

System.out.println("炖菜,吃馒头");

}

   

public void yanJiu() {

System.out.println("研究");

}

}

   

class DuoTaiTest2 {

public static void main(String[] args) {

//测试

//南方人

Person p = new SouthPerson();

p.eat();

System.out.println("-------------");

SouthPerson sp = (SouthPerson)p;

sp.eat();

sp.jingShang();

System.out.println("-------------");

   

//北方人

p = new NorthPerson();

p.eat();

System.out.println("-------------");

NorthPerson np = (NorthPerson)p;

np.eat();

np.yanJiu();

}

}

抽象类:

抽象类的概述:

动物不应该定义为具体的东西,而且动物中的吃,睡等也不应该是具体的。

我们把一个不是具体的功能称为抽象的功能,而一个类中如果有抽象的功能,该类必须是抽象类。

   

抽象类的特点:

A:抽象类和抽象方法必须用abstract关键字修饰

B:抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类

C:抽象类不能实例化

因为它不是具体的。

抽象类有构造方法,但是不能实例化?构造方法的作用是什么呢?

用于子类访问父类数据的初始化

D:抽象的子类

a:如果不想重写抽象方法,该子类是一个抽象类。

b:重写所有的抽象方法,这个时候子类是一个具体的类。

   

抽象类的实例化其实是靠具体的子类实现的。是多态的方式。

Animal a = new Cat();

demo:

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();

}

}

   

抽象类的成员特点:

成员变量:既可以是变量,也可以是常量。

构造方法:有。

用于子类访问父类数据的初始化。

成员方法:既可以是抽象的,也可以是非抽象的。

   

抽象类的成员方法特性:

A:抽象方法 强制要求子类做的事情。

B:非抽象方法 子类继承的事情,提高代码复用性。

Demo:

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();

}

}

猫狗案例

具体事物:猫,狗

共性:姓名,年龄,吃饭

   

分析:从具体到抽象

:

成员变量:姓名,年龄

构造方法:无参,带参

成员方法:吃饭(猫吃鱼)

   

:

成员变量:姓名,年龄

构造方法:无参,带参

成员方法:吃饭(狗吃肉)

   

因为有共性的内容,所以就提取了一个父类。动物。

但是又由于吃饭的内容不一样,所以吃饭的方法是抽象的,

而方法是抽象的类,类就必须定义为抽象类。

   

抽象动物类:

成员变量:姓名,年龄

构造方法:无参,带参

成员方法:吃饭();

   

实现:从抽象到具体

动物类:

成员变量:姓名,年龄

构造方法:无参,带参

成员方法:吃饭();

   

狗类:

继承自动物类

重写吃饭();

   

猫类:

继承自动物类

重写吃饭();

Demo:

//定义抽象的动物类

abstract class Animal {

//姓名

private String name;

//年龄

private int age;

   

public Animal() {}

   

public Animal(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();

}

   

//定义具体的狗类

class Dog extends Animal {

public Dog() {}

   

public Dog(String name,int age) {

super(name,age);

}

   

public void eat() {

System.out.println("狗吃肉");

}

}

   

//定义具体的猫类

class Cat extends Animal {

public Cat() {}

   

public Cat(String name,int age) {

super(name,age);

}

   

public void eat() {

System.out.println("猫吃鱼");

}

}

   

//测试类

class AbstractTest {

public static void main(String[] args) {

//测试狗类

//具体类用法

//方式1

Dog d = new Dog();

d.setName("旺财");

d.setAge(3);

System.out.println(d.getName()+"---"+d.getAge());

d.eat();

//方式2

Dog d2 = new Dog("旺财",3);

System.out.println(d2.getName()+"---"+d2.getAge());

d2.eat();

System.out.println("---------------------------");

   

Animal a = new Dog();

a.setName("旺财");

a.setAge(3);

System.out.println(a.getName()+"---"+a.getAge());

a.eat();

   

Animal a2 = new Dog("旺财",3);

System.out.println(a2.getName()+"---"+a2.getAge());

a2.eat();

   

}

假如我们在开发一个系统时需要对员工类进行设计,员工包含3个属性:姓名、工号以及工资。

经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。

请使用继承的思想设计出员工类和经理类。要求类中提供必要的方法进行属性访问。

   

分析:

普通员工类

成员变量:姓名、工号以及工资。

成员方法:工作

经理类:

成员变量:姓名、工号以及工资,奖金属性

成员方法:工作

   

实现:

员工类:

普通员工类:

经理类:

Demo:

//定义员工类

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");

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();

}

}

一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?

A:可以。

B:不让创建对象。

   

abstract不能和哪些关键字共存?

private        冲突

final        冲突        

static        无意义

接口:

   

接口的特点:

A:接口用关键字interface表示        

interface 接口名 {}

B:类实现接口用implements表示

class 类名 implements 接口名 {}

C:接口不能实例化

那么,接口如何实例化呢?

按照多态的方式来实例化。

D:接口的子类

a:可以是抽象类。但是意义不大。

b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)

   

由此可见:

A:具体类多态(几乎没有)

B:抽象类多态(常用)

C:接口多态(最常用)

demo:

//定义动物培训接口

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();

}

}

接口成员特点

成员变量;只能是常量,并且是静态的。

默认修饰符:public static final

建议:自己手动给出。

构造方法:接口没有构造方法。

成员方法:只能是抽象方法。

默认修饰符:public abstract

建议:自己手动给出。

   

所有的类都默认继承自一个类:Object

Object 是类层次结构的根类。每个类都使用 Object 作为超类。

demo:

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("--------------");

}

}

类与类:

继承关系,只能单继承,可以多层继承。

类与接口:

实现关系,可以单实现,也可以多实现。

并且还可以在继承一个类的同时实现多个接口。

接口与接口:

继承关系,可以单继承,也可以多继承。

demo:

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();

}

}

   

   

   

demo:

猫狗案例,加入跳高的额外功能

   

分析:从具体到抽象

猫:

姓名,年龄

吃饭,睡觉

狗:

姓名,年龄

吃饭,睡觉

   

由于有共性功能,所以,我们抽取出一个父类:

动物:

姓名,年龄

吃饭();

睡觉(){}

   

猫:继承自动物

狗:继承自动物

   

跳高的额外功能是一个新的扩展功能,所以我们要定义一个接口

接口:

跳高

   

部分猫:实现跳高

部分狗:实现跳高

实现;

从抽象到具体

   

使用:

使用具体类

  

//定义跳高接口

interface Jumpping {

//跳高功能

public abstract void jump();

}

   

//定义抽象类

abstract class Animal {

//姓名

private String name;

//年龄

private int age;

   

public Animal() {}

   

public Animal(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 Cat extends Animal {

public Cat(){}

   

public Cat(String name,int age) {

super(name,age);

}

   

public void eat() {

System.out.println("猫吃鱼");

}

}

   

//具体狗类

class Dog extends Animal {

public Dog(){}

   

public Dog(String name,int age) {

super(name,age);

}

   

public void eat() {

System.out.println("狗吃肉");

}

}

   

//有跳高功能的猫

class JumpCat extends Cat implements Jumpping {

public JumpCat() {}

   

public JumpCat(String name,int age) {

super(name,age);

}

   

public void jump() {

System.out.println("跳高猫");

}

}

   

//有跳高功能的狗

class JumpDog extends Dog implements Jumpping {

public JumpDog() {}

   

public JumpDog(String name,int age) {

super(name,age);

}

   

public void jump() {

System.out.println("跳高狗");

}

}

   

class InterfaceTest {

public static void main(String[] args) {

//定义跳高猫并测试

JumpCat jc = new JumpCat();

jc.setName("哆啦A");

jc.setAge(3);

System.out.println(jc.getName()+"---"+jc.getAge());

jc.eat();

jc.sleep();

jc.jump();

System.out.println("-----------------");

   

JumpCat jc2 = new JumpCat("加菲猫",2);

System.out.println(jc2.getName()+"---"+jc2.getAge());

jc2.eat();

jc2.sleep();

jc2.jump();

   

//定义跳高狗并进行测试的事情自己完成。

}

}

demo:

老师和学生案例,加入抽烟的额外功能

   

分析:从具体到抽象

老师:姓名,年龄,吃饭,睡觉

学生:姓名,年龄,吃饭,睡觉

   

由于有共性功能,我们提取出一个父类,人类。

   

人类:

姓名,年龄

吃饭();

睡觉(){}

   

抽烟的额外功能不是人或者老师,或者学生一开始就应该具备的,所以,我们把它定义为接口

   

抽烟接口。

   

部分老师抽烟:实现抽烟接口

部分学生抽烟:实现抽烟接口

   

实现:从抽象到具体

   

使用:具体

  

//定义抽烟接口

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();

   

//测试老师留给自己练习

}

}

抽象类和接口的区别:

A:成员区别

抽象类:

成员变量:可以变量,也可以常量

构造方法:有

成员方法:可以抽象,也可以非抽象

接口:

成员变量:只可以常量

成员方法:只可以抽象

   

B:关系区别

类与类

继承,单继承

类与接口

实现,单实现,多实现

接口与接口

继承,单继承,多继承

   

C:设计理念区别

抽象类 被继承体现的是:"is a"的关系。抽象类中定义的是该继承体系的共性功能。

接口 被实现体现的是:"like a"的关系。接口中定义的是该继承体系的扩展功能。

形式参数和返回值的问题

形式参数:

基本类型

引用类型

类名:需要的是该类的对象

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

接口:需要的是该接口的实现类对象

Demo:

类名:需要的是该类的对象

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());

}

}

demo:

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

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(p);

}

}

Demo:

接口:需要的是该接口的实现类对象

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);

}

}

返回值类型

基本类型:

引用类型:

:返回的是该类的对象

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

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

Demo:

:返回的是该类的对象

class Student {

public void study() {

System.out.println("Good Good Study,Day Day Up");

}

}

   

class StudentDemo {

public Student getStudent() {

//Student s = new Student();

//Student ss = s;

   

//Student s = new Student();

//return s;

return new Student();

}

}

   

class StudentTest2 {

public static void main(String[] args) {

//需求:我要使用Student类中的study()方法

//但是,这一次我的要求是,不要直接创建Student的对象

//让你使用StudentDemo帮你创建对象

StudentDemo sd = new StudentDemo();

Student s = sd.getStudent(); //new Student(); Student s = new Student();

s.study();

}

}

Demo:

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

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();

}

}

demo:

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

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();

}

}

链式编程:

每次调用完毕方法后,返回的是一个对象。

   

Demo:

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();

}

}

包(package):

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:回到和包根目录在同一目录的地方,然后运行

带包运行。

demo:

package cn.itcast;

   

class HelloWorld {

public static void main(String[] args) {

System.out.println("HelloWorld");

}

}

   

导包:

格式:import 包名;

这种方式导入是到类的名称。

注意:我们用谁就导谁。

   

面试题:

package,import,class有没有顺序关系?

有。

package > import > class

   

Package:只能有一个

import:可以有多个

class:可以有多个,以后建议是一个

权限修饰符的范围:

修饰符:

权限修饰符:private,默认的,protectedpublic

状态修饰符:staticfinal

抽象修饰符:abstract

   

类:

权限修饰符:默认修饰符,public

状态修饰符:final

抽象修饰符:abstract

   

用的最多的就是:public

   

成员变量:

权限修饰符:private,默认的,protectedpublic

状态修饰符:staticfinal

   

用的最多的就是:private

   

构造方法:

权限修饰符:private,默认的,protectedpublic

   

用的最多的就是:public

   

成员方法:

权限修饰符:private,默认的,protectedpublic

状态修饰符:staticfinal

抽象修饰符:abstract

   

用的最多的就是:public

   

除此以外的组合规则:

成员变量:public static final

成员方法:public static

public abstract

public final

   

*/

//此处不允许使用修饰符private

//此处不允许使用修饰符protected

//此处不允许使用修饰符static

public class Demo {

//成员变量

private int x = 10;

int y = 20;

protected int z = 30;

public int a = 40;

public final int b = 50;

public static int c = 60;

public static final int d = 70;

//此处不允许使用修饰符abstract

//abstract int e = 80;

   

//构造方法

private Demo(){}

   

Demo(String name){}

   

protected Demo(String name,int age) {}

   

public Demo(String name,int age,String address) {}

   

//此处不允许使用修饰符static

//public static Demo(){}

//此处不允许使用修饰符final

//public final Demo() {}

//此处不允许使用修饰符abstract

//public abstract Demo(){}

   

//成员方法

//static void show() {}

//abstract void show();

//final void show(){}

}

内部类的概述和讲解:

内部类概述:

把类定义在其他类的内部,这个类就被称为内部类。

举例:在类A中定义了一个类B,类B就是内部类。

   

内部的访问特点:

A:内部类可以直接访问外部类的成员,包括私有。

B:外部类要访问内部类的成员,必须创建对象。

demo:

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) {

   

}

}

内部类位置

成员位置:在成员位置定义的类,被称为成员内部类。        

局部位置:在局部位置定义的类,被称为局部内部类。

   

   

成员位置:在成员位置定义的类,被称为成员内部类。

Demo:

class Outer {

private int num = 10;

   

//成员位置

/*

class Inner {

   

}

*/

   

   

public void method() {

//局部位置

class Inner {

   

}

}

}

   

class InnerClassDemo2 {

public static void main(String[] args) {

   

}

}

成员内部类:

如何直接访问内部类的成员。

外部类名.内部类名 对象名 = 外部类对象.内部类对象;

Demo:

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();

}

}

 

成员内部类的修饰符:

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();

Demo:

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();

}

}

局部内部类

A:可以直接访问外部类的成员

B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能

   

面试题:

局部内部类访问局部变量的注意事项?

A:局部内部类访问局部变量必须用final修饰

B:为什么呢?

局部变量是随着方法的调用而调用,随着调用完毕而消失。

而堆内存的内容并不会立即消失。所以,我们加final修饰。

加入final修饰后,这个变量就成了常量。既然是常量。你消失了。

我在内存中存储的是数据20,所以,我还是有数据在使用。

Demo:

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();

}

}

匿名内部类

就是内部类的简化写法。

   

前提:存在一个类或者接口

这里的类可以是具体类也可以是抽象类。

   

格式:

new 类名或者接口名(){

重写方法;

}

   

本质是什么呢?

是一个继承了该类或者实现了该接口的子类匿名对象。

Demo:

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();

}

}

 

posted @ 2017-07-03 18:56  殷瑜泰  阅读(157)  评论(0编辑  收藏  举报