Java 是面向对象的高级编程语言,面向对象的特色如下:
- 面向对象具备 形象、封装、继承、多态 等个性;
- 面向对象能够将简单的业务逻辑简单化,加强代码复用性;
- 面向对象是一种常见的思维,比拟合乎人们的思考习惯。
面向过程和面向对象是什么?
- 面向过程是一种让程序的性能依照先后顺序执行的编程思维,每一个性能都是一步一步实现。
- 面向对象是将性能、事务高度抽象化的编程思维,把问题拆分成很多步骤,每一步都要进行形象,从而造成对象。程序通过对不同对象的调用,以此来解决问题。
二者的区别
- 面向过程是自顶向下的设计模式,要思考到每一个模块应该要分解成那些子模块,每一个子模块还要分解成更小的子模块,直到把模块合成为一个一个的函数(或者办法)。面向过程的最小程序单元是函数,每一个函数负责实现一个性能,用于接管输出的数据,函数进行解决,输入后果。
- 面向对象最小的程序单元是类,当软件系统宏大起来的时候,易于保护
对象 & 类
在大多面向对象的语言都应用 class
定义类,类就是对一系列对象的形象,类好比是快递的外包装,类外面的内容就示意这个对象的定义;例如:
class Javaer{}
这样,就申明了一个名字为 Javaer
的类,在 Java 中,能够通过 new 来创立这个对象:
Javaer javaer = new Javaer();
在 Java 中,类的命名要恪守 驼峰命名法,
骆驼式命名法(Camel-Case)又称驼峰式命名法,是电脑程式编写时的一套命名规定(常规)。正如它的名称 CamelCase 所示意的那样,是指混合应用大小写字母来形成变量和函数的名字。程序员们为了本人的代码能更容易的在同行之间交换,所以多采取对立的可读性比拟好的命名形式。
创建对象
在应用 Java 过程中,都是和对象打交道,Java 中的所有都能够看作是对象,但尽管如此,咱们操作对象,却是对对象的 援用:
Door key;
如上代码中创立的只是援用,并非一个对象;如果要想正确的创立一个对象并且不在编译的过程中出错,那么就须要在创建对象援用时同时把一个对象赋给它。
Door key = new Door();
在 Java 中,一旦创立了一个援用,就心愿它能与一个新的对象进行关联,通常应用 new
操作符来实现这一目标。
属性和办法
对于一个类,最根本的因素就是要有 属性 和办法;
属性又被称为字段:
Class Door {
int a;
Key key;
}
办法就是函数,办法的根本组成包含 办法名称、参数、返回值和办法体
public int get(){return 1;}
在下面的示例中,get
是办法名称,()
内是办法接管的参数、return
前面的是办法的返回值(如果是 void 办法,则不须要返回值),{}
里的是办法体。
构造方法
Java 中有一种非凡的 构造方法,又被叫做结构器或者构造函数。构造方法就是在创建对象的时候保障每个对象都被初始化。构造方法只在创建对象的时候调用一次,它没有参数类型和返回值,它的名称要和类名保持一致,并且构造方法能够有多个。
Class Door{
int number;
String color;
public Door(){}
public Door(int number){}
public Door(String color){}
public Door(int number,String color){}}
上述代码中定义了一个 Door
类,然而却没有参数类型和返回值,而且有多个同名的 Door() 办法,每个办法的参数列表也不同,其实这是面向对象特色 –多态 的体现,后文会介绍。定义好构造方法后,咱们就能创立一个 Door
对象了。
class creatDoor{public static void main(String[] args) {Door door1 = new Door();
Door door2 = new Door(1);
Door door3 = new Door("yellow");
Door door4 = new Door(1,"yellow");
}
}
如果类中没有定义任何构造方法,那么 JVM 会为你主动生成一个构造方法,如下
class Door {
int number;
String color;
}
class createDoor {public static void main(String[] args) {Door door1 = new Door();
}
}
默认的构造方法也被称为默认结构器或者无参结构器。
这里须要留神一点的是,即便 JVM 会为你默认增加一个无参的结构器,然而如果你手动定义了任何一个构造方法,JVM 就不再为你提供默认的结构器,你必须手动指定,否则会呈现编译谬误。
办法重载
重载在 Java 中是一个很重要的概念,它是类名的不同表现形式,上文提到的构造函数,是重载的一种,另外一种重载就是办法的重载。
public class Door {
int number;
String color;
public Door(){}
public Door(int number){}
public int getDoor(int number){return 1;}
public String getDoor(String color){return "color";}
}
如上所示,有 Door 的构造函数的重载,也有 getDoor 办法的重载。
如果有几个雷同的办法名字,Java 如何晓得你调用的是哪个办法呢?
每个重载的办法都有举世无双的参数列表。其中包含参数的类型、程序、参数数量等,满足一种一个因素就形成了重载的必要条件:
- 办法名称必须雷同。
- 参数列表必须不同(个数不同、或类型不同、参数类型排列程序不同等)。
- 办法的返回类型能够雷同也能够不雷同。
- 仅仅返回类型不同不足以成为办法的重载。
- 重载是产生在编译时的,因为编译器能够依据参数的类型来抉择应用哪个办法。
办法的重写
办法重写的形容是对 子类和父类
之间的。
而重载是产生同一个类中的。
class Food {public void eat(){System.out.printl('eat food');
}
}
class Fruit extends Food{
@Override
public void eat(){System.out.printl('eat fruit');
}
}
上述代码中,就含有重写的范例,子类 Fruit 中的办法和父类 Food 的办法雷同
所以重写的规范是:
- 重写的办法必须要和父类保持一致,包含 返回值类型, 办法名, 参数列表 也都一样。
- 重写的办法能够应用
@Override
注解来标识 - 子类中重写办法的拜访权限不能低于父类中办法的拜访权限。
初始化
咱们在创立一个对象,应用 new 创建对象的时候,实际上是调用了这个对象无参数的构造方法进行的初始化。这个无参数的构造函数能够暗藏,由 JVM 主动增加。也就是说,构造函数可能确保类的初始化。
class Door{public Door(){}}
成员初始化
成员初始化有两种模式
- 编译器默认指定的字段初始化,根本数据类型的初始化
类型 | 初始值 |
---|---|
boolean | false |
char | /u0000 |
byte | (byte)0 |
short | (short)0 |
int | 0 |
long | 0L |
float | 0.0f |
double | 0.0d |
其余数据类型,如 String,其初始值默认为 null
- 指定数值的初始化
int a = 11;
结构器初始化
结构器能够用来对某些办法和某些动作进行初始化,从而确定初始值:
public class Number{
int n;
public Number(){n = 11;}
}
利用构造函数,可能把 n 的值初始化为 11。
初始化程序
- 动态属性:static 结尾定义的属性
- 静态方法块:static {} 包起来的代码块
- 一般属性:非 static 定义的属性
- 一般办法块:{} 包起来的代码块
- 构造函数:类名雷同的办法
- 办法:一般办法
要验证初始化的程序,最好的办法就是写代码实际失去
public class TheOrder {
// 动态属性
private static String staticField = getStaticField();
// 静态方法块
static {System.out.println(staticField);
System.out.println("静态方法块初始化");
}
// 一般属性
private String field = getField();
// 一般办法块
{System.out.println(field);
}
// 构造函数
public TheOrder() {System.out.println("构造函数初始化");
}
public static String getStaticField() {
String statiFiled = "Static Field Initial";
return statiFiled;
}
public static String getField() {
String filed = "Field Initial";
return filed;
}
// 主函数
public static void main(String[] argc) {new TheOrder();
}
}
最终输入后果为
Static Field Initial
静态方法块初始化
Field Initial
构造函数初始化
那么初始化程序就是:
- 动态属性初始化
- 静态方法块初始化
- 一般属性初始化
- 一般办法块初始化
- 构造函数初始化
this 和 super
this
和 super
都是 Java 中的关键字
this
this
这个关键字只能用在办法的办法体内。当一个对象创立后,JVM 就会给这个对象调配援用本人的指针,这个指针的名字就叫做 this
。
this
示意的以后的对象,能够用来调用办法、属性以及对象自身。
public class Test{
private int number;
private String username;
private String password;
private int x = 100;
public Test(int n){number = n;// 这个能够写为 this.number = n;}
public Test(int i, String username, String password){
// 成员变量和参数同名,成员变量被屏蔽,用 "this. 成员变量" 的形式拜访成员变量.
this.username = username;
this.password = password;
}
// 默认不带参数的构造方法
public Test(){this(0, "未知", "空");// 通过 this 调用另外一个构造方法.
}
public Test(String name){this(1, name, "空");/*
* 通过 this 调用另外一个构造方法. 尽管下面的两种构造方法都是编译通过的。然而并没有理论的意义。个别咱们会在参数多的构造函数外面去用 this 调用参数少的构造函数(并且只能放在办法体外面的第一行)。* 示例外面的这种构造方法就相当于给了三个参数(其中两个参数曾经定了,另一个参数在这个构造方法传入)。*/
}
public Test(int i, String username){this(i, username, null);// 通过 this 调用另外一个构造方法.
}
}
this
应用办法总结
- 通过 this 调用本类中另一个构造方法,用法是 this (参数列表),这个仅仅在类的构造方法中能够用,并且只能放在类的构造方法的办法体的第一句。别的中央不能用。
- 办法参数或者办法中的局部变量和成员变量同名的状况下,成员变量被屏蔽,此时要拜访成员变量则须要用“this. 变量名”的形式来援用变量。然而,在没有同名的状况,能够间接用成员变量的名字,而不必 this,用了也是正确的(看起来更加的直观)。
- 在办法中,须要援用该办法所属类的以后对象的时候,间接用 this.
super
- 在子类的构造方法中要调用父类的构造函数,用“super(参数列表)”的形式调用,参数不是必须的(如果子类的构造方法没有某个参数,然而父类的构造函数外面有这个参数,那么在 super() 的参数列表里的相应地位,传入参数 null)。
- 如果子类重写了父类的某一个办法。(也就是子类和父类有雷同的办法定义,然而有不同的办法体),此时,咱们能够通过 “super. 成员办法名 ” 来调用父类外面的这个办法。
面向对象三大个性
封装
封装在 Java 中又称访问控制权限,访问控制权限其实最外围就是一点:只对须要的类可见。
Java 中成员的拜访权限共有四种,别离是 public、protected、default、private,它们的可见性如下
同一个类 | 同一个包 | 不同包的子类 | 不同包的非子类 | |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | |
默认(default) | √ | √ | ||
private | √ |
继承
继承是所有 OOP 语言和 Java 语言不可短少的组成部分。
继承是 Java 面对对象编程技术的一块基石,是面对对象的三大特色之一,也是实现软件复用的重要伎俩,继承能够了解为一个对象从另一个对象获取属性的过程。
当咱们筹备编写一个类时,发现某个类已有咱们所须要的成员变量和办法,如果咱们想复用这个类的成员变量和办法,即在所编写类中不必申明成员变量就相当于有了这个成员变量,不必定义方法就相当于有了这个办法,那么咱们能够将编写的类申明为这个类的子类即继承。
源类,基类,超类 或者 父类 都是一个概念
导出类,继承类,子类 也都是同一个概念
继承中最常应用的两个关键字是 extends 和 implements。
这两个关键字的应用决定了一个对象和另一个对象是否是 IS-A (是一个)关系。
通过应用这两个关键字,咱们能实现一个对象获取另一个对象的属性。
所有 Java 的类均是由 java.lang.Object 类继承而来的,所以 Object 是所有类的先人类,而除了 Object 外,所有类必须有一个父类。
继承的语法
class Father{
private int i;
protected int j;
public void func(){}
}
class Son extend Father{
public int k;
public void func(){}
}
留神:如类申明语句中没有 extends 子句,则该类为 java.lang 包中的 Object 的子类。这就阐明了 java 中的代码其实都有一个继承的关系,只不过是继承 Object 这个 java 中最基本的父类。
继承的特点
- 子类领有父类非 private 的属性和办法,子类继承的父类办法和成员变量能够当作本人的办法和成员变量一样被子类的实例办法应用。
- 子类能够有本人属性和办法,即子类能够在父类的根底上对父类进行扩大。
- 子类能够用本人的形式实现父类的办法。(重写或者笼罩)
多态
多态是同一个行为具备多个不同表现形式或状态的能力。多态就是同一个接口,应用不同的实例而执行不同操作。
多态性是面向对象编程的又一个重要特色,它是指在父类中定义的属性和办法被子类继承之后,能够具备不同的数据类型或体现出不同的行为,这使得同一个属性或办法在父类及其各个子类中具备不同的含意。对面向对象来说,多态分为编译时多态和运行时多态。其中编译时多态是动态的,次要是指办法的重载,它是依据参数列表的不同来辨别不同的办法。通过编译之后会变成两个不同的办法,在运行时谈不上多态。而运行时多态是动静的,它是通过动静绑定来实现的,也就是大家通常所说的多态性。
e.g. 彩色打印机和黑白打印机都是打印机,然而他们打印进去的货色色彩不一样。这就是多态
多态实现的条件
- 继承:在多态中必须存在有继承关系的子类和父类。
- 重写:子类对父类中某些办法进行从新定义,在调用这些办法时就会调用子类的办法,如果没有重写的话在父类中就会调用。当子类对象调用重写的办法时,调用的是子类的办法,而不是父类中被重写的办法。要想调用父类中被重写的办法,则必须应用关键字 super。
- 向上转型:在多态中须要将子类的援用赋给父类对象,只有这样该援用才既能能够调用父类的办法,又能调用子类的办法。
public class Person {public void drink(){System.out.println("喝咖啡");
}
public void eat(){System.out.println("吃点货色");
}
}
public class Man extends Person {public void drink(){System.out.println("喝冰美式");
}
}
public class Test {public static void main(String[] args) {Person p = new Man();
p.drink();
p.eat();}
}
输入:喝冰美式
吃点货色
多态的长处
- 打消类型之间的耦合关系
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性
接口和抽象类
接口
接口(英文:Interface),在 Java 编程语言中是一个形象类型,是形象办法的汇合,接口通常以 interface
来申明。一个类通过继承接口的形式,从而来继承接口的形象办法。
接口并不是类,编写接口的形式和类很类似,然而它们属于不同的概念。类形容对象的属性和办法。接口则蕴含类要实现的办法。除非实现接口的类是抽象类,否则该类要定义接口中的所有办法。
接口无奈被实例化,然而能够被实现。一个实现接口的类,必须实现接口内所形容的所有办法,否则就必须申明为抽象类。
接口和类类似点:
- 一个接口能够有多个办法。
- 接口文件保留在.java 结尾的文件中,文件名应用接口名。
- 接口的字节码文件保留在.class 结尾的文件中。
- 接口相应的字节码文件必须在与包名称相匹配的目录构造中。
接口和类的区别:
- 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的办法必须是形象办法。
- 接口不能蕴含成员变量,除了 static 和 final 变量。
- 接口不是被类继承了,而是要被类实现。
- 接口反对多重继承。
接口的申明
[可见度] interface 接口名称 [extends 其余类名]{
// 申明变量
// 形象办法
}
范例:
public interface TestInterface{public void eat();
public void drink();}
接口的实现
类实现接口的时候,类要实现接口中所有的办法。否则,类必须申明为形象的类。
范例:
public class Test implements TestInterface{public void eat(){System.out.println("吃货色");
}
public void drink(){System.out,println("喝水");
}
public static void main(String args[]){Test t = new Test();
t.eat();
t.drink();}
}
在实现接口的时候,要留神:
- 一个类能够同时实现多个接口。
- 一个类只能继承一个类,然而能实现多个接口。
- 一个接口能继承另一个接口,这和类之间的继承比拟类似。
抽象类
一个类中没有蕴含足够的信息来描述一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它性能仍然存在,成员变量、成员办法和构造方法的拜访形式和一般类一样。
因为抽象类不能实例化对象,所以抽象类必须被继承,能力被应用。也是因为这个起因,通常在设计阶段决定要不要设计抽象类。
父类蕴含了子类汇合的常见的办法,然而因为父类自身是形象的,所以不能应用这些办法。
在 Java 中用 abstract class 来定义抽象类。
public interface Test {void ColorTest();
}
abstract class WhiteDog implements Dog{public void ColorTest(){System.out.println("Color is white");
}
abstract void MMiniTest();}
在抽象类中,具备如下特色
- 如果一个类中有形象办法,那么这个类肯定是抽象类,也就是说,应用关键字
abstract
润饰的办法肯定是形象办法,具备形象办法的类肯定是抽象类。实现类办法中只有办法具体的实现。 - 抽象类中不肯定只有形象办法,抽象类中也能够有具体的办法,你能够本人去抉择是否实现这些办法。
- 抽象类中的束缚不像接口那么严格,你能够在抽象类中定义 构造方法、形象办法、一般属性、办法、动态属性和静态方法
- 抽象类和接口一样不能被实例化,实例化只能实例化
具体的类