面向对象语言的三大特性:
- 封装: 封装从字面上来理解就是包装的意思,专业点就是信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。系统的其他对象只能通过包裹在数据外面的已经授权的操作来与这个封装的对象进行交流和交互。也就是说用户是无需知道对象内部的细节,但可以通过该对象对外的提供的接口来访问该对象。
- 继承: 继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码,能够大大的提高开发的效率。关于继承总结三点:1、子类拥有父类非private的属性和方法。2、子类可以拥有自己属性和方法,即子类可以对父类进行扩展。3、子类可以用自己的方式实现父类的方法。
- 多态:多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
类和对象
类是Java语言中最重要的“数据类型”,类声明的变量被称作对象,即类是用来创建对象的模板。类的实现包括两部分:类声明和类体。基本格式为:
class 类名 {
//类的成员变量
//类的成员方法
//类体的内容等
}
其中:class是关键字,用来定义类。“class 类名”是类的声明部分,类名必须是合法的Java标识符。两个大括号以及之间的内容是类体。
1.成员变量:成员变量是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问。
数据类型 变量名称[=值]
2.成员方法:
[权限修饰符] [返回值类型]方法名([参数类型 参数名])[throws 异常类型]{
//方法体
return 返回值;
}
其中,权限修饰符可以是 private、public,protected中的任意一个,也可以不写,主要用来控制方法的访问权限。返回值类型用来指定方法返回数据的类型,可以是任何类型,如果方法不需要返回值,则使用void关键字;一个成员方法既可以有参数,也可以没有参数,参数可以是对象,也可以是基本数据类型的变量。
成员方法参数三种形式:
- 值参数 值参数表明实参与形参之间按值传递,当使用值参数的方法被调用时,编译器为形参分配存储单元,然后将对应的实参的值复制到形参中,由于是值类型的传递方式,所以,在方法中对值类型的形参的修改并不会影响实参。
- 引用参数 如果在给方法传递参数时,参数的类型是数组或者其他引用类型,那么,在方法中对参数的修改会反映到原有的数组或者其他引用类型上,这种类型的方法参数被称之为引用参数。
- 不定长参数 声明方法时,如果有若干个相同类型的参数,可以定义为不定长参数,该类型的参数声明如下∶ 权限修饰符 返回值类型 方法名(参数类型... 参数名) ==注意∶== 参数类型和参数名之间是三个点,而不是其他数量或省略号。
3.构造方法
构造方法是一个与类同名的方法,对象的创建就是通过构造方法完成的。每当类实例化一个对象时,类都会自动调用构造方法。 构造方法的特点如下∶
- 构造方法没有返回类型,也不能定义为void。
- 构造方法的名称要与本类的名称相同。
- 构造方法的主要作用是完成对象的初始化工作,它能把定义对象的参数传给对象成员。
如果类中没有明确定义构造方法,则编译器会自动创建一个不带参数的默认构造方法。
class Book{
public Book(){ //(无参)构造方法
}
}
除此之外,在类中定义构造方法时,还可以为其添加一个或者多个参数,即有参构造方法,语法如下:
class Book {
public Book(int args){ //有参构造方法
//对成员变量进行初始化
}
}
4..this关键字
- this关键字虽然可以调用成员变量和成员方法,但Java语言中最常规的调用方式是使用"对象.成员变量"或"对象.成员方法"进行调用。
- 既然 this关键字和对象都可以调用成员变量和成员方法,那么this关键字与对象之间具有怎样的关系呢?
- 事实上,this关键字引用的就是本类的一个对象,在局部变量或方法参数覆盖了成员变量时,如上面代码的情况,就要添加this关键字明确引用的是类成员还是局部变量或方法参数。
- 如果省略this关键字直接写成name = name,那只是把参数name赋值给参数变量本身而已,成员变量name的值没有改变,因为参数name在方法的作用域中覆盖了成员变量name。
- 其实,this关键字除了可以调用成员变量或成员方法之外,还可以作为方法的返回值。 例如,在项目中创建一个类文件,在该类中定义Book类型的方法,并通过过this关键字进行返回。
public class Book{
public getBook(){
return this; //返回Book类引用
}
}
5.static关键字
静态变量:在Java程序中,如果把共享的变量用static修饰,那么该变量就是静态变量。
静态方法:如果想要使用类中的成员方法,需要先将这个类进行实例化,但有些时候不想或者无法创建类的对象时,还要调用类中的方法才能够完成业务逻辑,这种情况下就可以使用静态方法。
静态代码块:在类的成员方法之外,用static修饰代码区域可以称之为静态代码块。定义一块静态代码块,可以完成类的初始化操作,在类声明时就会运行。 语法如下∶
public class StaticTest {
static {// 此处编辑执行语句
}
}
示例:
public class Animal {
public static int num = 0;
private String name;
private int id;
private int age;
static {
System.out.println("静态代码块");
}
{
System.out.println("非静态代码块");
}
public Animal(String name) {
this.name=name;
System.out.println("构造方法");
}
public void method() {
System.out.println("成员方法");
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction(){
System.out.println("我是" + name + ".");
}
public void count(int n){
num += n;
}
public static void main(String[] args){
Animal animal;
Animal dog = new Animal("dog");
Animal cat = new Animal("cat");
}
}
6.类的主方法
主方法是类的入口点,它指定了程序从何处开始,提供对程序流向的控制。Java编译器通过主方法来执行程序。
主方法的语法如下∶
public static void main(String[] args){
// 方法体
}
在主方法的定义中可以看到主方法具有以下特性∶
- 主方法是静态的,所以如要直接在主方法中调用其他方法,则该方法必须也是静态的。
- 主方法没有返回值。
- 主方法的形参为数组。其中 args[0]~args[n] 分别代表程序的第一个参数到第n+1个参数,可以使用 args.length 获取参数的个数。
源文件声明规则
当在一个源文件中定义多个类,并且还有import语句和package语句时,要特别注意这些规则。
- 一个源文件中只能有一个 public 类
- 一个源文件可以有多个非 public 类
- 源文件的名称应该和 public 类的类名保持一致。例如:源文件中 public 类的类名是 Employee,那么源文件应该命名为Employee.java。
- 如果一个类定义在某个包中,那么 package 语句应该在源文件的首行。
- 如果源文件包含 import 语句,那么应该放在 package 语句和类定义之间。如果没有 package 语句,那么 import 语句应该在源文件中最前面。
- import 语句和 package 语句对源文件中定义的所有类都有效。在同一源文件中,不能给不同的类不同的包声明。
继承
在java中使用extends 关键字来声明子类继承于某父类,如下:
class 父类 {
}
class 子类 extends 父类 {
}
继承类型
继承又分单继承和多重继承,Java不支持多继承。
单继承和多重继承。单继承是指一个子类最多只能有一个父类。多继承是一个子类可以有二个以上的父类。
继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类。
多重继承例子如下:
public class A{}
public class B extends A{}
public class C extends B{}
继承关键字:
- implements:ava除了extends,还可以用implements关键字来实现继承。Java中不支持多重继承,但是用implements可以实现多个接口,相当于使得Java具有多继承的特性。
- super:引用当前对象的父类成员
- this:指向当前类的引用。
- final即最终的,不可变的。final的功能是将类定义为不可继承的,也可以用于修饰方法,被修饰的方法不可被子类重写。
public class Animal {
public static int num = 0;
private String name;
private int id;
private int age;
public Animal(String myName){
name = myName;
System.out.println(myName);
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction(){
System.out.println("我是" + name + ".");
}
public void count(int n){
num += n;
}
public static void main(String[] args){
tiger t = new tiger("tiger");
rabbit r = new rabbit("rabbit");
t.eat();
t.sleep();
t.introduction();
}
}
class tiger extends Animal{
public tiger(String myName) {
super(myName);
}
}
class rabbit extends Animal{
public rabbit(String myName){
super(myName);
}
}
构造器
子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。
如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。
class SuperClass{
private int n;
SuperClass(){
System.out.println("SuperClass()");
}
SuperClass(int n){
System.out.println("SuperClass(int n)");
}
}
class SubClass extends SuperClass{
private int n;
SubClass(){
System.out.println("SubClass");
}
SubClass(int n){
super(300);
System.out.println("SubClass(int n):"+n);
}
}
class SubClass2 extends SuperClass{
private int n;
SubClass2(){
super(300);
System.out.println("SubClass2");
}
SubClass2(int n){
System.out.println("SubClass2(int n):"+n);
this.n = n;
}
}
public class TestSuperSub {
public static void main(String[] args){
System.out.println("------SubClass 类继承------");
SubClass sc1 = new SubClass();
SubClass sc2 = new SubClass(100);
System.out.println("------SubClass2 类继承------");
SubClass2 sc3 = new SubClass2();
SubClass2 sc4 = new SubClass2(200);
}
}
多态的转型
向上转型
当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作。
父类类型 变量名=new 子类类型()
向下转型
当要使用子类特有功能时。
子类类型 变量名=(子类类型) 父类类型的变量;
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
Animal a = new Cat(); // 向上转型
a.eat(); // 调用的是 Cat 的 eat
Cat c = (Cat)a; // 向下转型
c.work(); // 调用的是 Cat 的 work
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat)a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
}
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}