### 面向对象编程
面向对象编程思想
随着互联网项目需求越来越复杂,面向过程不能满足,使用面向对象。
将功能(方法/函数)封装进对象、强调了具备了功能的对象,以类/对象为最小单位,考虑谁来做。
两个要素:类和对象
面向对象程序设计的重点是类的设计
类的设计就是类的成员的设计
类和对象的使用(面向对象思想落地的实现):
1、创建类,设计类的成员
2、创建类的对象
3、通过“对象,属性”和“对象,方法”调用对象的结构next
-类
类是一组相关属性和行为的组合
类是对一类事物的描述,是抽象的,概念上的定义。
实际存在的该类事物的每个个体,因为也称为实例(instance)
面向对象程序设计的重点是类的设计
类的设计就是类的成员的设计。
Java代码世界是由诸多个不同的功能的类构成的。再大的项目都是由类实现的。
例外情况是接口,就不是类构成的。
Java有丰富的类库和第三方库
-类和对象的创建
-类的结构
事物描述类
创建Person类的属性和方法:
public class Person{
String name;
int age = 1;
boolean isMale;
public void eat(){
System.out.println("eat")
}
public void talk(String language){
System.out.println("talk"+language)
}
}
-成员一:属性Field
属性:对应类中的成员变量
field=属性=成员变量=域、字段
String name;
int age = 1;
boolean isMale;
-=成员变量Member
类中,方法外,储存在堆内存
不需要给初始化值
1.就是属性,直接定义在类的一对{}内的属性
....
都指非static
2.可以使用权限修饰符:(结构被调用可见性的大小),跟封装性有关系
private
public
static
缺省=不写的情况下
protected
3.有默认初始化值,根据其类型
整型(byte short int long=0)
浮点型(float double=0.0)
字符型(char=0或、=\u0000)
布尔型(false)
引用数据类型(类、数组、接口=null)
string=null
4.属性在内存中加载到堆空间
public class Student{
string name;-声明一个姓名string变量
int age;声明一个年龄int变量
}
5.随着对象的创建而存在,随着对象的消失而消失
-private
可以修饰成员变量和成员方法
被private修饰的成员只能在本类中才能访问。
控制数据安全性。
在Demo创建对象的时候就无法调用。
针对private修饰的成员变量,我们会相应的提供getXxx()和setXxx()方法,用于获取和设置成员变量的值和方法。
private int age
public void setAge(int a){
if(a<0||a>200){
System.out.println("wrong age");
}else{
age=a;
}
}
public int getAge(){
return age;
}
在Demo中就可以调用private的成员变量。
public static void main..
s.setAge(00);
-成员二:方法/函数
描述类应该具有的功能
行为=方法=功能:对应类中的成员方法
method=成员方法=函数
函数式一块代码块,接收零个或多个参数,做一个特殊的事情,并返回零个或一个值。
任何函数都必须是类的成员,写在class里。
public void eat(){
System.out.println("eat")
}
public void talk(String language){
System.out.println("talk"+language)
}
调用函数invoke a method
int z= max(x,y)
方法是功能的封装,通过对象来调用功能。
-定义方法/函数的结构
类中方法的声明和使用:
格式:
权限修饰符 返回值类型 方法名(形参列表)
刻画类应该具有的功能
math类:sqrt()\random()。。
scanner类:nextXxx。。
Array类:sort()\binarySearch()\toString()\equals()
方法声明:
1.public void eat(){}没参没返回
2.public void sleep(int hour){}有参没返
3.public String getName(){} 没参有返
return name调用属性
public void setAge(int i) { //声明方法setAge
age = i; //将参数i的值赋给类的成员变量age
4.public String getNation(String nation){}有参有返
return nation
方法的格式:
修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2.。。。){
方法体;
return返回值
}
public static void main(){
for(int i=0; i<20; i++){
System.out.println("Hello World!")
}
}
方法中只能调用方法或属性,不可以在方法内部定义方法。
-修饰符modifier
可以有,可以没有
都是有意义的
public谁都可以访问
static这个函数是静态的,整个类的
没有static说明是属于这个类的某一个对象,而不是属于整个类的
-访问权限修饰符Access Modifier(关键字)
封装性
-四种权限关键字
-private
-属性/方法
-封装性
-缺省/default
什么也不写
-protected
-public
public谁都可以访问的类
在一个java源文件中可以声明多个class。但是,只能最多有一个类声明为public,并且和类源文件同名。
-其他关键字
-package关键字
-import
-static属于整个类的
static这个函数是静态的,整个类的
比如main方法(JDK直接调用的方法)
不能用this,不依附于对象。
没有static说明是属于某个类的某一个对象,而不是属于整个类的。
public static void main....
静态方法不能访问非静态成员方法和非静态成员变量(因为不依赖于对象),但在非静态成员方法中可以不用对象访问静态方法和变量。
带有static的方法,可以通过类的名称去直接调用。其他的需要创建对象。
所以方便在没有创建对象的情况下来进行调用(静态方法/变量/)。
不依赖对象进行访问,只要类被加载了,就可以通过类名去进行访问,
-this
this:代表所在类的对象引用。当前调用对象的引用。用在属性和参数同名时。
它在方法内部使用,即这个方法所属对象的引用;
它在构造器内部使用,表示该构造器正在初始化的对象。
this 可以调用类的属性、方法和构造器
什么时候使用this关键字呢?
当在方法内需要用到调用该方法的对象时,就用this。
具体的:我们可以用this来区分属性和局部变量。 比如:this.name = name;
成员变量=属性
局部变量=参数
-super关键字
-final
-变量
-类
-方法
-abstract
-类
-方法
-返回值类型return value type
有返回值&没有返回值
1.如果有返回值,必须在方法声明时指定返回值的类型,同时,方法中需要使用return关键字来返回指定类型的变量或常量。
2.没有返回值,则声明方法是,使用void来表示。使用return表示结束方法。
3.定义方法该不该有返回值。根据要求,凭经验。
-void空类型
没有返回值return的方法
调用时直接调用,不用传递参数
void修饰的方法的调用:
public class MethodTest(){
public static void main(String[] args)
}
public static void helloWorld(){
for (int i=1;i<10,i++){
System.out.println("HelloWorld")
}
}
练习
-int、float、double、string
有return值,调用时需传递参数
-方法名method name
属于标识符,遵循标识符的规则和规范,符合见名知意。
-main入口函数
程序的入口是main方法,格式是固定的
-形参列表parameter list
相当于数学里的自变量,可以没有,也可以有多个,用逗号隔开,用括号括起来。
每个参数都要有参数类型和参数名。
形参:方法声明时的参数
方法可以声明0个1个或多个形参。
格式:(数据类型1 形参1,数据类型2 形参2,。。。)
-参数结构
-参数类型
String类型的数组参数列表
String[]
-基本类型
-引用类型
-数组
-类
-接口
-参数名args
-参数类型
-无形参
-有形式参数formal parameter
-方法参数的使用
-方法的重载
即同名方法,参数不同
使用重载方法,可以为编程带来方便。
在调用方法的时候,Java虚拟机会通过传入的参数列表的个数和类型的不同来区别。
重载的概念
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数 类型不同即可。
重载的特点:
与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类 型)。调用时,根据方法参数列表的不同来区别。
重载示例:
//返回两个整数的和
int add(int x,int y){return x+y;}
//返回三个整数的和
int add(int x,int y,int z){return x+y+z;}
//返回两个小数的和
double add(double x,double y){return x+y;}
public class PrintStream {
public static void print(int i) {......} public static void print(float f) {......} public static void print(String s) {......}
public static void main(String[] args) { print(3);
print(1.2f);
print("hello!");
-可变个数形参
定义可变长度参数的方法
说明:
1.声明格式:方法名(参数的类型名 ...参数名)
public void test1(String ... books){
System.out.println("****形参长度可变的test1方法****");
}
2.可变参数:方法参数部分指定类型的参数个数是可变多个:0个,1个或多个 3. 可变个数形参的方法与同名的方法之间,彼此构成重载
4.可变参数方法的使用与方法参数部分使用数组是一致的
5.方法的参数部分有可变形参,需要放在形参声明的最后
6.在一个方法的形参位置,最多只能声明一个可变个数形参
-值传递机制
Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本 (复制品)传入方法内,而参数本身不受影响。
形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参
形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参
引用类型:类(对象)(string类),数组
-方法体statements method header
代码功能语句
包含局部变量
调用一个功能时,主要是对方法体的体现。
之后大部分时间都是在写方法体。
方法的使用:
1.在方法内可以调用当前类的属性和方法。递归方法。
2.方法里不能定义另一个方法。
-方法的使用
-成员方法
和定义方法一样,但是去掉static
public void study(){
Sys...
}
public void eat(){
Sys...
}
-递归方法/函数
resursion
方法的使用中,可以调用当前类的属性和方法。
特殊的,方法A中又调用了方法A--递归方法。
递归方法:一个方法体内调用它自身。
方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执 行无须循环控制。
递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死 循环。
死循环会出现栈溢出:Stack Overflow
public int getSum(int n){
if(n==1){
return 1;
}else{
return n + getSum(n-1);
}
}
-数组快排
-斐波那契数列
规律:一个数等于前两个数之和
1 1 2 3 4 5 8 13 21 34 55
f(n)=f(n-1)+f(n-2)
-汉诺塔问题
-局部变量=本地变量
1.声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量,
储存在栈内存。
方法形参:
public void talk(String language-形参)
方法内:
public void eat(){
String food = "pizza";
System.out.println("I like eat "+food)
}
2.不可以使用权限修饰符,只有final
3.没有初始化值,在调用局部变量前一定要赋值初始化,形参在到用时赋值即可。
4.局部空间在内存中加载在栈空间
5.随着方法的调用而存在,随着方法的调用完毕而消失
-方法与数组
-遍历数组
-获取最值
-元素的和
-返回值return
表明结果是什么,以及结束程序。
一个函数里面可以有多个return。
找到了,返回相对应数据类型的值,没找到返回-1(Java默认)
使用:
1.使用范围:方法体内
2.作用:1)void结束方法
2)有返回值的,返回所数据。
3.注意点:return关键字后面不可以声明执行类型。
-成员三:构造器constructor
不是方法,跟方法不一样
构造器作用:
没有定义,系统会默认提供一个空参构造器
创建对象;给对象进行初始化
一个类中可以定义多个构造器(重载)
一旦显示的定义了类的构造器之后,系统就不再提供默认的空参构造器
一个类中,至少一个构造器
定义构造器的格式:
权限修饰符 类名(形参列表)
给对象的类型进行初始化
和类同名的方法
没有写构造方法的时候,系统会默认创建一个无参无返回值的构造器。
定义构造器格式:
1.权限修饰符
2.方法名和类名相同
3.没有返回值的方法,连void都没
4.(形参列表)p1.name
Person p1 = new Person("Tom")
public person(String n){
name=n;
}
Sys。。。。
*没有的时候显示默认的,写了就会显示写的。
调用:
通过new这个关键字调用
创建类对象:new+构造器()
person p1 = new person();
构造器是创建对象
注 意:
Java语言中,每个类都至少有一个构造器
默认构造器的修饰符与所属类的修饰符一致
一旦显式定义了构造器,则系统不再提供默认构造器
一个类可以创建多个重载的构造器
父类的构造器不可被子类继承
-成员四:代码块
-static
-非static
-final关键字
-成员五:内部类
-抽象类与抽象方法
-接口interface
一方面,有时必须从几个类中派生出一个子类,继承它们所有的属性和方
法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果。
另一方面,有时必须从几个类中抽取出一些共同的行为特征,而它们之间又 没有is-a的关系,仅仅是具有相同的行为特征而已。例如:鼠标、键盘、打 印机、扫描仪、摄像头、充电器、MP3机、手机、数码相机、移动硬盘等都 支持USB连接。
接口就是规范,定义的是一组规则,体现了现实世界中“如果你是/要...则 必须能...”的思想。继承是一个"是不是"的关系,而接口实现则是 "能不能" 的关系。
接口的本质是契约,标准,规范,就像我们的法律一样。制定好后大家都 要遵守。
-API
API:application programming interface,应用程序编程接口。是jave提供的基本编程接口
定义好了各种动作的方法,直接调用接口即可。
java API指的就是JDK中提供的各种功能的java类。
在下载的JDK里面含有的
API文档:java语言提供了大量的基础类,因此Oracle也为这些基础类提供了相应的API文档,用于告诉开发者如何使用这些类,以及这些类里包含的方法。
如何使用:
-常用类库(外部类)
在JDK里面的java常用开发工具包内提供
不需要关心这些类如何实现
是需要学会使用即可
-Scanner()
-random()
-object()
-wrapper()
-常用类
-math类:sqrt()\random()...
-scanner类:nextXXX()...
-array类:sort()\binarySearch()\toString()\equals()...
-常用内部类的使用
-JavaBean
所谓javaBean,是指符合如下标准的Java类:
类是公共的
有一个无参的公共的构造器
有属性,且有对应的get、set方法
-抽象类
-内部类
-匿名内部类
-枚举类
-object类
-包装(Wrapper)类
-字符串string类
-Subtopic 1
-Subtopic 2
-Subtopic 3
-面向对象三大特性
-封装
封装性的体现:
1.私有属性
2.私有方法
3.单例模式。。
将类的属性私有化private,同时提供公共的public方法来获取getXxx和设置setXxx
对属性的设置(setXxx)
legs属性声明成private以后不可见,不能调用,调用使用接口setLegs方法来调用
public int setLegs(int a)-有形参
legs=a
对属性的获取(getXxx)
public int getLegs()-没有形参
-权限修饰符
封装性的体现,需要权限修饰符来配合。
1.Java规定的有4种权限:(从小到大排)
private
2.四种权限可以用来修饰类及类的内部结构:属性,方法,构造器,内部类
3.具体的,4种权限都可以用来修饰类的内部结构,修饰类的话,只能使用缺省,public
-getXxx/setXxx
public class Person{
private int age;
public int getAge() { //声明方法getAge()
return age; }
public void setAge(int i) { //声明方法setAge
age = i; //将参数i的值赋给类的成员变量age
}
-包装(Wrapper)类
-继承
为什么要有继承?
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中, 那么多个类无需再定义这些属性和行为,只要继承那个类即可。
此处的多个类称为子类(派生类),单独的这个类称为父类(基类 或超类)。可以理解为:“子类 is a 父类”
类继承语法规则:
class Subclass extends SuperClass{ }
public student extends person{
}
作用:
继承的出现减少了代码冗余,提高了代码的复用性。
继承的出现,更有利于功能的扩展。
继承的出现让类与类之间产生了关系,提供了多态的前提。
子类继承了父类,就继承了父类的方法和属性。
在子类中,可以使用父类中定义的方法和属性,也可以创建新的数据和
方法。
在Java 中,继承的关键字用的是“extends”,即子类不是父类的子集,
而是对父类的“扩展”。
关于继承的规则:
子类不能直接访问父类中私有的(private)的成员变量和方法。
-父类/子类
Java只支持单继承和多层继承,不允许多重继承
一个子类只能有一个父类
一个父类可以派生出多个子类
class SubDemo extends Demo{ } //ok
class SubDemo extends Demo1,Demo2...//error
-object类
在java中,java.lang.Object 类是所有java类的最高层父类,是唯一一个没有父类的类:
如果在类的声明中未使用extends 关键字指明其父类,则默认父类为Object 类。
-子类对象实例化
子类继承所以父类的属性和方法
-单继承/多层继承
在java中,只允许单继承,也就是说 一个类最多只能显示地继承于一个父类。但是一个类却可以被多个类继承,也就是说一个类可以拥有多个子类。
-static关键字
-方法的重写override/overwrite
定义:在子类中可以根据需要对从父类中继承来的方法进行改造,也称
为方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。
修改的是方法体。
要求:
1.子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表 2. 子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型
3.子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限
子类不能重写父类中声明为private权限的方法
4.子类方法抛出的异常不能大于父类被重写方法的异常
注意:
子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为 static的(不是重写)。因为static方法是属于类的,子类无法覆盖父类的方法。
-this关键字
-super关键字
在Java类中使用super来调用父类中的指定操作:
super可用于访问父类中定义的属性 super可用于调用父类中定义的成员方法 super可用于在子类构造器中调用父类的构造器
注意: 尤其当子父类出现同名成员时,可以用super表明调用的是父类中的成员
super的追溯不仅限于直接父类
super和this的用法相像,this代表本类对象的引用,super代表父类的内存 空间的标识
-调用属性和方法
调用属性:
子类重写属性不会覆盖父类的属性,用super.可以调用父类属性,this访问本类中的属性(super,this常省略)
调用方法:
子类重写方法会覆盖父类的方法(带有this.),一定要加super,没重写的可以不加
-调用构造器
子类中所有的构造器默认都会访问父类中空参数的构造器
当父类中没有空参数的构造器时,子类的构造器必须通过this(参 数列表)或者super(参数列表)语句指定调用本类或者父类中相应的 构造器。同时,只能”二选一”,且必须放在构造器的首行
如果子类构造器中既未显式调用父类或本类的构造器,且父类中又 没有无参的构造器,则编译出错
-多态
1.理解多态性:可以理解为一个事物的多态性。
2.何为多态性
子类对象的多态性:父类的引用p2指向子类的对象Man
person p2 = new Man()
person p3 = new Woman
3.多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法-虚拟方法调用
注意:子类自己的方法是不能调用的,方法必须是父类有的,子类重写的,实际运行的是子类重写父类的方法
Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明 该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。简 称:编译时,看左边;运行时,看右边。
若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism) 多态情况下,“看左边”:看的是父类的引用(父类中不具备子类特有的方法)
“看右边”:看的是子类的对象(实际运行的是子类重写父类的方法)
4.多态性的使用前提:
类的继承关系和方法的重写
多态性不适用于属性(看左父类)
-虚拟方法调用
虚拟方法调用(Virtual Method Invocation)
正常的方法调用
Person e = new Person();
e.getInfo();
Student e = new Student(); e.getInfo();
虚拟方法调用(多态情况下) 子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父
类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法 确定的。
Person e = new Student();
e.getInfo(); //调用Student类的getInfo()方法 编译时类型和运行时类型
编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类 的getInfo()方法。——动态绑定
-向下转型(向上转型=多态)
有了对象的多态以后,内存中实际上是加载了子类特有的属性和方法,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法,子类特有的属性和方法不能调用。
如何才能调用子类特有的属性和方法?
使用强制类型转换符(自动类型提升)
较高级的基本数据类型-》较低级的基本数据类型
Man m1 = (Man)p2;
m1.earnMoney();
...
向上转型:多态
向下转型:使用instanceof进行判断
-instanceof操作符(关键字)
a instanceof A:
判断对象a是否是类A的实例。如果是返回true,如果不是返回false。
即为了在向下强转之前不出现异常,先做一个判断。
if(p2 instanceof Woman)
if(p2 instanceof Man)
如果a instanceof A返回true,则a instanceof B也返回true。其中,类B是类A的父类。
-单例设计模式
-抽象
-抽象类
-抽象方法
-接口
-容器
-设计模式
-Java新特性
-泛型
-元注解
-装箱/拆箱
-枚举
-可变参数
-Lambda表达式
-Stream API
-Data/Time API
### 应用程序开发(类库)
-异常处理
-断点调试debug
可以通关断点调试插卡程序的执行流程
-JDBC
-Oracle/MySQL
-反射
通过对象倒推类
-网络编程Java Web
-多线程编程
-Java常用类库
-枚举类/注解
-Java集合Map
-泛型
-I/O输入/输出流编程NIO
-网络
-集合