[TOC]
0x08 JAVA面向对象 1.面向对象思想概述 Q:我们学习编程是为了什么?
一个Java程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作。
简要介绍下类、对象、方法和实例变量的概念:
类:是一组相关的属性和行为的集合
对象:对象是类的一个实例,有状态和行为即该类事物的具体体现。
方法:方法就是行为,一个类可以有很多方法,逻辑运算、数据修改以及所有动作都是在方法中完成的(函数)
属性:属性就是状态,及变量如String Color=”red”;
实例变量:每个对象都有独特的实例变量,对象的状态由这些实例变量的值决定。
Q:面向对象开放与设计概念:
面向对象开发就是不断的创建对象使用对象,指挥对象做事情。
面向对象设计,其实就是在管理和维护对象之间的关系。
Q:面向对象思想特点?
a:是一种更符合我们思想习惯的思想
b:可以将复杂的事情简单化
c:将我们从执行者变成了指挥者,角色发生了转换
Java中最基本的单位是类,Java中用class描述事物也是如此
成员变量==事物的属性, 就是该事物的描述信息(事物身上的名词)
成员方法==事物的行为, 就是该事物能够做什么(事物身上的动词)
面向对象特征:
封装(encapsulation)
继承(inheritance)
多态(polymorphism)
2.面向对象使用 面向对象的使用在一个java文件中写两个类:一个基本的类,一个测试类(包含主程序入口的类) 建议:文件名称和测试类名称一致。
Q:定义类其实就是定义类的成员(成员变量和成员方法)
a:成员变量(属性)和以前定义变量是一样的,只不过位置发生了改变。在类中方法外。
b:成员方法(行为)和以前定义方法是一样的,只不过把static去掉,后面在详细讲解static的作用。
[TOC]
0x08 JAVA面向对象 1.面向对象思想概述 Q:我们学习编程是为了什么?
一个Java程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作。
简要介绍下类、对象、方法和实例变量的概念:
类:是一组相关的属性和行为的集合
对象:对象是类的一个实例,有状态和行为即该类事物的具体体现。
方法:方法就是行为,一个类可以有很多方法,逻辑运算、数据修改以及所有动作都是在方法中完成的(函数)
属性:属性就是状态,及变量如String Color=”red”;
实例变量:每个对象都有独特的实例变量,对象的状态由这些实例变量的值决定。
Q:面向对象开放与设计概念:
面向对象开发就是不断的创建对象使用对象,指挥对象做事情。
面向对象设计,其实就是在管理和维护对象之间的关系。
Q:面向对象思想特点?
a:是一种更符合我们思想习惯的思想
b:可以将复杂的事情简单化
c:将我们从执行者变成了指挥者,角色发生了转换
Java中最基本的单位是类,Java中用class描述事物也是如此
成员变量==事物的属性, 就是该事物的描述信息(事物身上的名词)
成员方法==事物的行为, 就是该事物能够做什么(事物身上的动词)
面向对象特征:
封装(encapsulation)
继承(inheritance)
多态(polymorphism)
2.面向对象使用 面向对象的使用在一个java文件中写两个类:一个基本的类,一个测试类(包含主程序入口的类) 建议:文件名称和测试类名称一致。
Q:定义类其实就是定义类的成员(成员变量和成员方法)
a:成员变量(属性)和以前定义变量是一样的,只不过位置发生了改变。在类中方法外。
b:成员方法(行为)和以前定义方法是一样的,只不过把static去掉,后面在详细讲解static的作用。
1 2 3 4 5 6 7 8 9 10 11 12 * 创建对象并使用格式: * 类名 对象名 = new 类名(); * 对象名.变量名 * 对象名.方法名() this 关键字特点:* 代表当前对象的引用 this 的应用场景:- 用来区分成员变量和局部变量重名问题 - 可以区分多个对象
案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class Demo_Class { public static void main (String[] args) { Students stu = new Students(); stu.age = 13 ; stu.name = "Weiyigeek" ; stu.sex = '女' ; stu.study(); stu.sleep("Weiyi" ,1024 ); } } class Students { String name; char sex; int age; public void study () { System.out.println("姓名:" +name+" ,年龄:" +age+" ,性别:" +sex+"动作:正在学习" ); } public void sleep (String name,int age) { this .name = name; this .age = age; System.out.println("姓名:" +name+" ,年龄:" +age+" ,性别:" +this .sex+"动作:正在睡觉" ); } }
weiyigeek.top-this关键字
(1) 对象内存分析 三个引用有两个对象的引用指向同一个地址,对象的内存案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Demo_Classmemory { public static void main (String[] args) { Car c1 = new Car(); c1.color = "red" ; c1.run(); c1 = null ; Car c2 = new Car(); c2.color = "Black" ; c2.run(); Car c3 = c2; c3.run(); } } class Car { String color; public void run () { System.out.println(color); } }
weiyigeek.top-对象内存分析
补充: 如果没有任何引用指向该对象,那么该对象就会变成垃圾,JAVA中又完善的垃圾回收机制,会对其进行回收;
(2)成员变量和局部变量的区别 A:在类中的位置不同
成员变量:在类中方法外
局部变量:在方法定义中或者方法声明上
B:在内存中的位置不同
成员变量:在堆内存(成员变量属于对象,对象进堆内存)
局部变量:在栈内存(局部变量属于方法,方法进栈内存)
C:生命周期不同
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
D:初始化值不同
成员变量:有默认初始化值
局部变量:没有默认初始化值,必须定义/赋值,然后才能使用。
注意事项
局部变量名称可以和成员变量名称一样,在方法中使用的时候采用的是就近原则。
当局部内部类访问局部变量的时候,局部变量必须用finall修饰;
基本数据类型变量包括:byte,short,int,long,float,double,boolean,char,且初始化值与数值初始化值一致;
引用数据类型变量包括:数组,类,接口,枚举
案例:1 2 3 4 5 6 7 8 9 10 11 12 class Person { String name; int num; public void speak (int value) { int num = 10 ; System.out.println(name); System.out.println(num); } }
(2引用数据类型和基本数据类型调用的区别 在Java中,引用类型的变量非常类似于C/C++的指针,引用类型指向一个对象,指向对象的变量是引用变量。这些变量在声明时被指定为一个特定的类型比如 Employee、Puppy 等。
变量一旦声明后,类型就不能被改变了
对象、数组都是引用数据类型,所有引用类型的默认值都是null,一个引用变量可以用来引用任何与之兼容的类型。
例子:Site site = new Site(“Runoob”) #这里的Site
A:方法的参数是类名public void print(Student s){} //print(new Student());
如果你看到了一个方法的形式参数是一个类类型(引用类型),这里其实需要的是该类的对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Demo_ClassQuote { public static void main (String[] args) { print(10 ); Student s = new Student(); print(s); } public static void print (int x) { System.out.println(x); } public static void print (Student stu) { stu.name = "WeiyiGeek" ; stu.speak(); } } class Student { String name; public void speak () { System.out.println(name+"正在台上讲话!" ); } }
3.匿名对象概述与应用 Q:什么是匿名对象? 答:没有名字的对象
匿名对象应用场景:
a:调用方法,仅仅只调用一次的时候。
b:匿名对象可以作为实际参数传递
Q:匿名对象是否可以调用属性并赋值?有什么意义?
匿名对象可以调用属性,但是没有意义,因为调用后就变成垃圾
如果需要赋值还是用有名字对象
Q:匿名调用有什么好处吗? 答:节省代码,使代码更加简介;
注意:调用多次的时候不适合。匿名对象调用完毕就是垃圾,可以被垃圾回收器回收。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class Demo2_Car { public static void main (String[] args) { new Car().color = "red" ; new Car().num = 8 ; new Car().run(); method(new Car()); method(new Car()); } public static void method (Car c) { c.color = "red" ; c.num = 1024 ; c.run(); } } class Car { String color; int num; public void run () { System.out.println(color + ".|." + num); } }
weiyigeek.top-匿名对象内存图
4.封装 封装概述:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式,使用private关键字。 封装好处:
隐藏实现细节,提供公共的访问方式
提高了代码的复用性
提高安全性。
封装原则:
将不需要对外提供的内容都隐藏起来。
把属性隐藏,提供公共方法对其访问。
private关键字的概述和特点
a:是一个权限修饰符
b:可以修饰成员变量和成员方法
c:被其修饰的成员只能在本类中被访问
d:private仅仅是封装的一种体现形式,不能说封装就是私有(在学习包的时候具体实现,不同包中的类想调用其他包中私有成员变量,需要在该包下建立一个公共的方法来调用返回自身的成员变量 )
案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Demo_Encapsulation { public static void main (String[] args) { Encaps en = new Encaps(); en.name = "WeiyiGEEK" ; en.setID(500102123 ); System.out.println("用户ID值:" +en.getID()); en.getInfo(); } } class Encaps { String name; private long ID; public long getID () { return ID; } public void setID (long value) { ID = value; } public void getInfo () { System.out.println(name + " : " + ID); } }
5.构造对象 构造方法Constructor概述和格式:
A:构造方法概述和作用:给对象的数据(属性)进行初始化
B:构造方法格式特点
a:方法名与类名相同(大小也要与类名一致)
b:没有返回值类型连void都没有
,如果加上void及其他返回的数据类型,它便不是一个普通方法;
c:没有具体的返回值return;
构造方法的重载及注意事项: 重载:方法名相同,与返回值类型无关(构造方法没有返回值),只看参数列表
C:构造方法注意事项
a:如果我们没有给出构造方法,系统将自动提供一个无参构造方法。
b:如果我们给出了构造方法,系统将不再提供默认的无参构造方法。
注意这个时候如果我们还想使用无参构造方法,就必须自己给出;建议永远自己给出无参构造方法(重载)
案例1:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class Demo_Contructor { public static void main (String[] args) { Base b = new Base("Weiyigeek" ); System.out.println("Name:" +b.getName()+"\n" ); Base b1 = new Base(); System.out.println("Name:" +b1.getName()); Base b2 = new Base("Hacker" ); b2 = new Base("New Hacker" ); System.out.println("Name:" +b2.getName()); } } class Base { private String name = "Other" ; public Base (String name) { this .name = name; System.out.println("b对象 - 这是Base类的构造方法:name = " +this .name); } public Base () { this .name = "空参构造" ; System.out.println("b1对象 - 这是Base类的重载构造方法:" +this .name); } public String getName () { return this .name; } }
Q:画图说明一个对象的创建过程做了哪些事情?
Base s = new Base();
1,Base.class加载进内存
2,声明一个Base类型引用 s
3,在堆内存创建对象,
4,给对象中属性默认初始化值 null
5,属性进行显示初始化 Other
6,构造方法进栈,对对象中的属性赋值 weiyigeek,构造方法弹栈
7,将对象的地址值赋值给 s
8.对象调用getName方法进行输出属性值
(1) static关键字 关键字的特点:
a:随着类的加载而加载
b:优先于对象存在(随着字节码加载而加载,那时还没创建对象)
c:被类的所有对象共享,节约了内存
可以通过类名调用
其实它本身也可以通过对象名调用。
推荐使用类名调用。
静态修饰的内容一般我们称其为:与类相关的,类成员
Q:其实这个特点也是在告诉我们什么时候使用静态? 答:如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的。
比如:饮水机可以设置为静态(共享),而纸杯不可设置为静态修饰;共性用静态,特性用非进静态;
static关键字对象成员方法内存图案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class Demo_StaticMemory { public static void main (String[] args) { System.out.println("Person.country = " + Person.country); Person p1 = new Person("WeiyiGeek" , "001" ); p1.country = "重庆" ; p1.Info(); Person p2 = new Person("唯一" , "002" ); p2.Info(); System.out.println("Person.country = " + Person.country); } } class Person { String name; private String id; static String country = "未知城镇" ; public Person (String name,String id) { System.out.println("######进入构造方法!##########" ); this .name = name; this .id = id; } public void Info () { System.out.println("个人信息:\n姓名:" +this .name+"\tid:" +this .id+"\t城市:" +country); } }
weiyigeek.top-
(2)静态/非静态方法
静态方法只能访问静态的成员变量和静态的成员方法(静态只能访问静态)
静态方法:
成员变量:只能访问静态变量
成员方法:只能访问静态成员方法
非静态方法:
成员变量:可以是静态的,也可以是非静态的
成员方法:可是是静态的成员方法,也可以是非静态的成员方法
注意事项:
在静态方法中是没有this关键字的, 由于静态比对象先存在;静态是随着类的加载而加载,this是随着对象的创建而存在。
静态变量和成员变量的区别:静态变量也叫类变量,成员变量也叫对象变量
A:所属不同
静态变量属于类,所以也称为为类变量
成员变量属于对象,所以也称为实例变量(对象变量)
B:内存中位置不同
静态变量存储于方法区的静态区(节约空间)
成员变量存储于堆内存
C:内存出现时间不同
静态变量随着类的加载而加载,随着类的消失而消失
成员变量随着对象的创建而存在,随着对象的消失而消失
D:调用不同
静态变量可以通过类名调用,也可以通过对象调用
成员变量只能通过对象名调用
案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class Demo_StaticVariable { public static void main (String[] args) { Base1 b1 = new Base1(); b1.print(); Base1.print2(); } } class Base1 { int id = 1024 ; static int score = 78 ; public void print () { System.out.println("非静态方法:" +id); System.out.println(score); } public static void print2 () { System.out.println("静态方法:" +score); } }
(3)工具类建立帮助使用 Java Development Kit (JDK) 中有一个名为 javadoc 的程序,用来为 Java 程序产生HTML 文件形式的外部注释文档。Javadoc 支持一定数目的标记,标识注释文档中各段起始位置 的保留字。详情请参考 JDK javadoc 文档。
如果一个类中所有的方法都是静态的,此时需要再多做一步私有构造方法,目的是不让其他类创建本类对象;直接使用类型.静态方法/变量调用即可;
我们可以对工具类加入文档注释,通过javadoc命令生成说明书:
@author(提取作者内容)
@version(提取版本内容)
@param 参数名称//形式参数的变量名称
@return 函数运行完返回的数据
案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public class ArrayTools { private ArrayTools () {} public static int getArrMax (int [] arr) { int max = arr[0 ]; for (int i = 0 ; i < arr.length; i++) { max = max > arr[i] ? max:arr[i]; } return max; } } class Main1 { public static void main (String[] args) { int [] arr = {10 ,1 ,8 ,5 ,2 }; ArrayTools at = ArrayTools(){}; ArrayTools.getArrmax(arr); } }
weiyigeek.top-生成帮助
(4)代码块分类和描述
代码块概述:在Java中,使用{}括起来的代码被称为代码块。 代码块分类:
根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块(多线程讲解)。
常见代码块的应用:
a:局部代码块
在方法中出现;限定变量生命周期,及早释放,提高内存利用率
b:构造代码块 (初始化块)
在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行
c:静态代码块
在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且只执行一次。
一般用于加载驱动
案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 class Demo_Blockcode { static { System.out.println("1.主方法中的静态代码块" ); } public static void main (String[] args) { System.out.println("2.主方法main" ); { int x = 1024 ; System.out.println("3.主方法main中代码块" +x); } Baser b = new Baser(); } } class Baser { static { System.out.println("4.Base类的静态代码块" ); } public Baser () { System.out.println("7.Base类构造方法" ); } { System.out.println("5.Base类构造代码块" ); test(); } public void test () { System.out.println("6.Base类构造代码块调用的test()函数" ); } }
6.继承 继承(extends):让类与类之间产生关系,子父类关系;继承的好处:
a:提高了代码的复用性
b:提高了代码的维护性
c:让类与类之间产生了关系,是多态的前提 (没有继承就没有多态)
继承的弊端
类的耦合性增强了;开发的原则:高内聚,低耦合。
耦合:类与类的关系
内聚:就是自己完成某件事情的能力
Java中类的继承特点:
a:Java只支持单继承,不支持多继承(存在安全隐患,一个儿子只能有一个爹),有些语言是支持多继承,格式:extends 类1,类2,…
b:Java支持多层继承(继承体系)
如果想用这个体系的所有功能用最底层的类创建对象;如果想看这个体系的共性功能,看最顶层的类;
继承的注意事项:
a:子类只能继承父类所有非私有的成员(成员方法和成员变量)
b:子类不能继承父类的构造方法,但是可以通过super(马上讲)关键字去访问父类构造方法。
c:不要为了部分功能而去继承
Q:什么时候使用继承 答:继承其实体现的是一种关系:”is a”。
继承中成员变量/方法的关系:
a:不同名的变量; 同名的变量,会受到就近原则的影响;
b:不同名的方法; 同名的方法,子类父类有重名的方法时候子类将会重写父类方法;
案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 class Demo_ClassExtends { public static void main (String[] args) { grandChild child = new grandChild(); child.grandChildFun(); child.childFun(); child.parentFun(); } } class Parent { int num1 = 10 ; public Parent () { System.out.println("父类里面的构造方法!" ); } public void parentFun () { System.out.println("我是父类里面得方法-parentFun()" ); } private void show () { System.out.println("父类里的私有方法-继承的子类是无法访问的" ); } } class Child extends Parent { int num1 = 20 ; public void childFun () { System.out.println("我是子类里面得方法-childFun()" ); } } class grandChild extends Child { int num1 = 30 ; public void grandChildFun () { System.out.println("我是孙子类里面得方法-grandChildFun(); num1 = " + num1); } }
(1) super关键字 Q:this和super都代表什么
this:代表当前对象的引用,谁来调用我,我就代表谁
super:代表当前对象父类的引用
Q:this和super的使用区别
a:调用成员变量
this.成员变量 调用本类的成员变量,也可以调用父类的成员变量(关键点:父子类有重名的成员变量将显示本类的成员变量)
super.成员变量 调用父类的成员变量
b:调用构造方法
this(…) 调用本类的构造方法
super(…) 调用父类的构造方法
c:调用成员方法
this.成员方法 调用本类的成员方法,也可以调用父类的方法
super.成员方法 调用父类的成员方法
(2)继承中构造方法的关系 Q:为什么子类中所有的构造方法默认都会访问父类中空参数的构造方法呢?
因为子类会继承父类中的数据,可能还会使用父类的数据。
所以子类初始化之前,一定要先完成父类数据的初始化。
其实:每一个构造方法的第一条语句默认都是 super() 而Object类最顶层的父类
Q:父类没有无参构造方法,子类怎么办? 答:this与super进行解决;
注意事项:
super(…) 或者 this(….) 必须出现在构造方法的第一条语句上;
案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 class Demo_ClassSuper { public static void main (String[] args) { Son son = new Son(); son.print(); System.out.println("-------------------------" ); son = new Son(65536 ); son.print(); } } class Father extends Object { int father = 1024 ; public Father () { super (); System.out.println("父类 空参 构造方法" ); } public Father (int value) { this .father = value; System.out.println("父类 有参 构造方法" ); } } class Son extends Father { int father = 2048 ; public Son () { this (10000 ); System.out.println("子类 空参 构造方法" ); } public Son (int value) { super (value); System.out.println("子类 有参 构造方法" ); } public void print () { System.out.println("父类:" +super .father); System.out.println("子类:" +this .father); System.out.println("子类:" +father); } }
补充执行流程:
1,JVM调用main方法,main近栈;
2,遇到 Son son = new Son() 实例化,将父类/子类Father.class-Son.class分别加载进内存再创建对象
3,由于Java是分层继承初始化的,所有先初始化父类,再初始化子类;
4,进入子类空参构造,然后调用子类有参构造,调用父类的有参构造,然后依次进行输出;
5,父类中father成员变量值被改成10000,子类中father成员变量值没改变;
(3)继承中方法的重写
Q:什么是方法重写? 答:重写子父类出现了一模一样的方法(注意:返回值类型可以是子父类,这个我们学完面向对象讲)
方法重写的应用: 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。这样即沿袭了父类的功能,又定义了子类特有的内容。
方法重写注意事项:
a:父类中私有方法不能被重写:因为父类私有方法子类根本就无法继承
b:子类重写父类方法时访问权限不能更低:最好就一致(关键字public 权限为最低)
c:父类静态方法/子类也必须通过静态方法进行重写
其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解(静态只能覆盖静态)
子类重写父类方法的时候,最好声明一模一样。
案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 class Demo_ClassOverwrite { public static void main (String[] args) { IOS8 ios = new IOS8(); ios.call(); ios.siriSpeak(); IOS7.print(); } } class IOS7 { public void call () { System.out.println("使用 Phone 打电话!" ); } private void play () { System.out.println("使用 Phone 打玩游戏! - 私有方法不能被重写!" ); } public void siriSpeak () { System.out.println("Speak English!" ); this .play(); } public static void print () { System.out.println("使用 Phone 打印文章! -静态方法只能覆盖静态其实不算重写,多态的时候详细讲解" ); } } class IOS8 extends IOS7 { public void siriSpeak () { System.out.println("Speak Chinese!中文" ); super .siriSpeak(); } }
方法重写的面试题: Override和Overload的区别? 答:前者是重写,后者是重载;
方法重写:子类中出现了和父类中方法声明一模一样的方法,与返回值类型有关,返回值是一致(或者是子父类)的;
方法重载:本类中出现的方法名一样,参数列表个数类型不同的方法,与返回值类型无关。
子类对象调用方法的时候:先找子类本身再找父类。
案例2:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 class Demo_Demo2 { public static void main (String[] args) { Teacher tea = new Teacher("Weiyi" ,25 ); tea.eat(); tea.action(); System.out.println("------------------------" ); Studentss stu = new Studentss("Geek" , 18 ); stu.eat(); stu.action(); } } class Pub { String name; int age; public Pub (String name,int age) { this .name = name; this .age = age; System.out.println("Pub 类得有参构造方法" ); } public void eat () { System.out.println("共有类吃饭方法" ); } public void action () { System.out.println("将要被子类重写方法" ); } } class Teacher extends Pub { public Teacher (String name,int age) { super (name,age); System.out.println("Teacher 类得有参构造方法" ); } public void action () { System.out.println(this .name+" 【正在讲课!】" ); } } class Studentss extends Pub { public Studentss (String name, int age) { super (name,age); System.out.println("Student 类得有参构造方法" ); } public void action () { System.out.println(this .name+"【正在学习!】" ); } }
(4) final关键字 final(最终)关键字修饰类,方法以及变量的特点; final修饰特点:
修饰类,类不能被继承
修饰变量,变量就变成了常量,只能被赋值一次
修饰方法,方法不能被重写
final关键字修饰局部变量:
基本类型:是值不能被改变
引用类型:是地址值不能被改变,对象中的属性可以改变
Q:final修饰变量的初始化时机?
方法1:显示初始化必须设置final成员变量得值;
方法2:在对象构造完毕前即可,设置其final成员得变量值;
案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class Demo_Final { public static void main (String[] args) { DemoFinal fi = new DemoFinal(); final Dm1 o = new Dm1("Whoami" ); o.getName(); o.setName("Weiyigeek" ); o.getName(); } } class DemoFinal { public static final int NUM = 1024 ; final int COUNT; public DemoFinal () { COUNT = 1 ; System.out.println(this .NUM + " , " + this .COUNT); } } final class Dm1 { private String name; public Dm1 (String value) { this .name = value; } public void getName () { System.out.println(this .name); } public void setName (String value) { this .name = value; } public final void notOverride () { System.out.println("这是不能被重写得类方法" ); } }
7.多态 描述:多态(polmorphic)是指事物存在的多种形态;
多态特征:
要有继承关系
要有方法重用
要有父类引用指向子类对象
多态的好处与弊端?
好处:提高了代码的维护性(继承保证)/提高了代码的扩展性(由多态保证),可以当作形参也可以接收任意子类对象;
弊端:不能使用子类特有属性和行为;
代码体现多态:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 class Demo1_Polymorphic { public static void main (String[] args) { Cat c = new Cat(); c.eat(); Animal a = new Cat(); a.eat(); Animal wz = new Cat(); System.out.println("" + wz.name); wz.action(); } } class Animal { String name = "大类-猫科" ; public void eat () { System.out.println("动物正在吃饭!" ); } public void action () { System.out.println("动物正在做自己该做的事情!" ); } } class Cat extends Animal { String name = "小类-猫儿" ; public void eat () { System.out.println("猫儿吃鱼!" ); } public void action () { System.out.println("猫儿正在勤劳的抓老鼠!" ); } public void play () { System.out.println("猫儿玩耍中....." ); } } 猫儿吃鱼! 猫儿吃鱼! 大类-猫科 猫儿正在勤劳的抓老鼠!
多态中的成员访问特点:
成员变量: 编译看左边(父类变量),运行看左边(父类变量) , 声明对象看类型
成员方法: 编译看左边(父类方法),运行看右边(子类方法) , 注意在编译前是看的父类方法但是在实际运行中就看子类(动态绑定);
静态方法(不存在动态绑定):编译看左边(父类变量),运行看左边(父类变量) , 静态和类是非常的相似算不上重写所有还是左边的,只有非静态的成员方法编译看左边运行看右边
;
代码实例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 class Demo1_polymorphic1 { public static void main (String[] args) { Father f = new Son(); System.out.println("father 类定义" + f.num); Son s = new Son(); System.out.println("son 类定义:" + s.num); f.print(); s.print(); f.printf(); s.printf(); } } class Father { int num = 10 ; public void print () { System.out.println("我是一个父类" ); } public static void printf () { System.out.println("我是一个Father父类的静态方法" ); } } class Son extends Father { int num = 20 ; public void print () { System.out.println("我是一个子类" ); } public static void printf () { System.out.println("我是一个Son子类的静态方法" ); } } father 类定义10 son 类定义:20 我是一个子类 我是一个子类 我是一个Father父类的静态方法 我是一个Son子类的静态方法
weiyigeek.top-注意成员方法
(1)多态中的向上与向下转型 在开发中很少判断您是哪一个类型的然后来强转,就是直接采用父类类型参数接收对应的子类类型; 在开发中经常是您父类中具备的方法,然后子类来重写方法,然后把父类方法当作参数然后传入子类类型即可; 补充关键字: instanceof (判断前边的引用是否是后边的数据类型)
实际案例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 class Demo1_polymorphicSuperman { public static void main (String[] args) { Person p = new Superman(); System.out.println(p.name); p.测试(); Superman su = (Superman)p; System.out.println(su.name); su.测试(); su.fly(); method(new Cat()); method(new Dog()); } public static void method (Animal a) { if (a instanceof Cat) { Cat c = (Cat)a; c.eat(); c.catchMouse(); }else if (a instanceof Dog) { Dog d = (Dog)a; d.eat(); d.lookHome(); }else { a.eat(); } } } class Person { String name = "Person" ; public void 测试() { System.out.println("person人类测试!" );} } class Superman extends Person { String name = "Superman" ; public void 测试() { System.out.println("Superman超人测试!" );} public void fly () { System.out.println("去救人!" );} } class Animal { public void eat () {System.out.println("动物吃饭" );} } class Cat extends Animal { public void eat () {System.out.println("猫吃鱼" );} public void catchMouse () {System.out.println("抓老鼠" );} } class Dog extends Animal { public void eat () {System.out.println("狗吃肉" );} public void lookHome () {System.out.println("看家" );} }
weiyigeek.top-转型示例内存图
8.抽象 描述:抽象就是看不懂的不好理解的;
抽象类/方法的特点:
抽象类和抽象方法必须用abstract关键字修饰
抽象类:abstract class 类名 {} , 抽象方法:public abstract void eat() - 是没有方法体的;
抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口;
抽象类不能实例化
抽象类的子类:要么是抽象类,要么重写抽象类中的所有抽象方法
那么抽象类如何实例化呢? 答:按照多态的方式(多态的一种,抽象类多态),由具体的子类实例化。
抽象类的成员特点
a:成员变量:既可以是变量,也可以是常量。
abstract是否可以修饰成员变量? 不能修饰成员变量
b:有构造方法,用于子类访问父类数据的初始化。
c:成员方法:既可以是抽象的,也可以是非抽象的。
抽象类的成员方法特性:
a:抽象方法 强制要求子类做的事情。
b:非抽象方法 子类继承的事情,提高代码复用性。
abstract 不能和那些关键字共存:
static 静态方法, 使用类名.方法来调用静态方法是没有意义的,被修饰的方法无方法体:
final 定义常量/方法, 与abstract产生冲突一个是让子类重写一个是不让子类重写;
private 私有变量/方法,与abstract冲突一个是让子类看到并且强制重写,另外一个是被private修饰不让子类访问;
实际案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class abstractDemo { public static void main (String[] args) { Animal c = new Cat(); c.eat(); c.print(); } } abstract class Animal { int num1 = 10 ; final int num2 = 20 ; public void demo () {}; public void print () { System.out.println("【抽象类中可以有 非抽象成员方法 】" ); } public abstract void eat () ; } class Cat extends Animal { public void eat () { System.out.println("【多态重写】Cat eat Fishc!" ); } } abstract class CCat extends Animal { public void eat1 () { System.out.println("【抽象类子类】 mutil Cat eat Fishc!" ); } }
示例练习:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 public class abstractDemo1 { public static void main (String[] args) { Cat c = new Cat("1" , 8 ); Dog d = new Dog("1" , 12 ); System.out.println("Cat 姓名:" + c.getName() +" 年龄:" +c.getAge()); c.eat(); c.ability(); System.out.println("Dog 姓名:" + d.getName() +" 年龄:" +d.getAge()); d.eat(); d.ability(); } } abstract class Animal { private String name; private int age; public Animal () {}; public Animal (String name,int age) { this .name = name; this .age = age; } public void setName (String name) { this .name = name; } public String getName () { return name; } public void setAge (int age) { this .age = age; } public int getAge () { return age; } public abstract void eat () ; } class Cat extends Animal { public Cat () {}; public Cat (String name, int age) { super (name, age); } public void eat () { System.out.println("Cat eat Fishc!!" ); } public void ability () { System.out.println("Catch MOUSE!" ); } } class Dog extends Animal { public Dog () {}; public Dog (String name, int age) { super (name,age); } public void eat () { System.out.println("Cat eat Bone!!" ); } public void ability () { System.out.println("Catch House!" ); } }
执行结果:1 2 3 4 5 6 7 8 Cat 姓名:1 年龄:8 Cat eat Fishc!! Catch MOUSE! Dog 姓名:1 年龄:12 Cat eat Bone!! Catch House! Process finished with exit code 0
9.接口 接口的概述及其特点 接口概述:
从狭义的角度讲就是指java中的interface
从广义的角度讲对外提供规则
的都是接口
接口特点:
接口用关键字interface表示 : interface 接口名 {}
类实现接口用implements表示: * class 类名 implements 接口名 {}
接口的子类:
a:可以是抽象类,但是意义不大。
b:可以是具体类(普通类),要重写接口中的所有抽象方法。(推荐方案)
接口成员特点:
成员变量;只能是常量,并且是静态的并公共的。
默认修饰符:public static final; 建议自己手动给出。
构造方法:接口没有构造方法。
成员方法:只能是抽象方法,不能是非抽象方法;
默认修饰符:public abstract; 建议自己手动给出。
接口是不能实例化的,那么接口如何实例化呢 ? 答:按照多态的方式来实例化。
案例:演示接口以及接口成员特点1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 public class InterfaceDemo1 { public static void main (String[] args) { Inter i = new Demo(); i.print(); Inter j = new sub(); j.print(); String num1 = String.valueOf(i.num1); String num2 = String.valueOf(Inter.num2); System.out.println(num1 + num2); System.out.print(i.num1+" VS " +Inter.num2); } } interface Inter { int num1 = 1024 ; public static final int num2 = 1024 ; public abstract void print () ; } class Demo implements Inter { public Demo () { super (); } public void print () { System.out.println("[1].接口子类-普通类-抽象方法被调用" ); } } abstract class Demo1 implements Inter { public abstract void print () ; } class sub extends Demo1 { public void print () { System.out.println("[2.]接口子类-抽象类-多态方式-抽象方法被调用" ); } }
执行结果:1 2 3 4 [1].接口子类-普通类-抽象方法被调用 [2.]接口子类-抽象类-多态方式-抽象方法被调用 10241024 1024 VS 1024
抽象类和接口区别总结 , 成员区别:
抽象类:
成员变量:变量或常量
成员方法:可以是抽象,也可以是非抽象
构造方法: 有
接口:
成员变量:只可以是常量
成员方法:只可以是抽象
构造方法: 无
类与类,类与接口,接口与接口的关系:
a:类与类:
b:类与接口:
实现关系,可以单实现,也可以多实现。
并且还可以在继承一个类的同时实现多个接口。
c:接口与接口:
设计理念区别:
抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。
接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。
抽象类与接口区别案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 public class InterfaceDemo2 { public static void main (String[] args) { Cat1 c = new Cat1("Love" ,12 ); c.eat(); c.play(); JumpCat d = new JumpCat("baby" , 13 ); d.eat(); d.play(); } } abstract class AnimalFather { private String name; private int age; public AnimalFather (String name, int age) { this .name = name; this .age = age; } public String getName () { return this .name; } public abstract void eat () ; public abstract void play () ; } interface Jumping { public abstract void jump () ; } class Cat1 extends AnimalFather { public Cat1 (String name, int age) { super (name, age); } @Override public void eat () { System.out.println(super .getName() + "Cat eat Fishc!" ); } @Override public void play () { System.out.println(super .getName() + "Cat play 毛线" ); } } class JumpCat extends Cat1 implements Jumping { public JumpCat (String name, int age) { super (name, age); } public void jump () { System.out.println("Cat Jumping!" ); } }
执行结果:1 2 3 4 LoveCat eat Fishc! LoveCat play 毛线 babyCat eat Fishc! babyCat play 毛线
10.装饰设计模式 描述:装饰设计模式优点:耦合性没有这么强,便于功能的扩展;(值得学习借鉴)
基础实例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 public class Demo_Classdesign { public static void main (String[] args) { Tea t = new Tea(new Stu()); t.able(); } } interface code { public void able () ; } class Stu implements code { @Override public void able () { System.out.println("C" ); System.out.println("C++" ); System.out.println("VF" ); } } class Tea implements code { private Stu demo; public Tea (Stu demo) { super (); this .demo = demo; } @Override public void able () { demo.able(); System.out.println("### 扩展的技能 ###" ); System.out.println("Python" ); System.out.println("Perl" ); System.out.println("php" ); System.out.println("Javascript" ); System.out.println("Java" ); System.out.println("Node.js" ); System.out.println("HTML/XML" ); } }
11.工厂设计模式 1) 简单工厂模式 描述:简单工厂模式又叫静态工厂方法模式,它定义一个具体的工厂类负责创建一些类的实例;
优点:客户端不需要在负责对象的创建,从而明确了各个类的职责
缺点:这个静态工厂类负责所有对象的创建,如果有新的对象增加,或者某些对象的创建方式不同,就需要不断的修改工厂类,不利于后期的维护
基础示例1:简单工厂模式使用1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 public abstract class Animal { public abstract void eat () ; } class Dog extends Animal { @Override public void eat () { System.out.println("狗啃骨头!" ); } } class Cat extends Animal { @Override public void eat () { System.out.println("猫吃鱼儿!" ); } } public class Factory { public static Animal createanimal (String animalname) { if ("Dog" .equals(animalname)){ return new Dog(); }else if ("Cat" .equals(animalname)){ return new Cat(); }else { return null ; } } } public class Demo5_SimpleFactory { public static void main (String[] args) { Factory f1 = new Factory(); Dog d = (Dog)f1.createanimal("Dog" ); d.eat(); Cat c = (Cat)f1.createanimal("Cat" ); c.eat(); } }
执行接口:
2) 工厂方法模式(推荐) 概述:工厂方法模式中抽象工厂类负责定义创建对象的接口
,具体对象的创建工作由继承抽象工厂的具体类实现。
优点: 客户端不需要在负责对象的创建,从而明确了各个类的职责,如果有新的对象增加,只需要增加一个具体的类和具体的工厂类即可,不影响已有的代码,后期维护容易,增强了系统的扩展性;缺点: 需要额外的编写代码,增加了工作量;
基础示例: 值得学习1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 动物抽象类:public abstract Animal { public abstract void eat () ; } 具体狗类:public class Dog extends Animal {} 具体猫类:public class Cat extends Animal {} public interface Factory {public abstract Animal createAnimal () ;} class DogFactory implements Factory1 { @Override public Animal createAnimal () { return new Dog(); } } class CatFactory implements Factory1 { @Override public Animal createAnimal () { return new Cat(); } } public class Demo5_Factory { public static void main (String[] args) { DogFactory df = new DogFactory(); Dog d = (Dog)df.createAnimal(); d.eat(); CatFactory cf = new CatFactory(); Cat c = (Cat)cf.createAnimal(); c.eat(); } }