面向对象(object-oriented:OO)

一、类的构成

1、面向对象与面向过程

    面向对象是相对于面向过程而言的。面向过程注重的是过程,强调的是在完成的这个过程中的动作。面向对象注重的是对象,只要找到了这个对象,就拥有了这个对象所具有的一切功能。

    比如做饭,如果自己做饭的话,就需要自己准备食材,炊具等等,还要进行烹饪。但是当我们找到一个餐馆,这些事情就都不需自己做了,就等着吃饭就行了。此时餐馆就相当于一个对象,我们只要找到了这个餐馆,就拥有了这个餐馆具有的一切功能。

    面向对象是基于面向过程的。面向对象不一定优于面向过程,如果事物相对简单,适合用面向过程;如果事物比较复杂,适合于面向对象。

2、类和对象的关系

    根据一类事物进行抽取,将这一类事物用一个类表示,同时将这一类事物的共有特征抽取成属性,将这一类事物的共有行为抽取成了方法。类是对象的抽取/概括。通过new关键字来产生对应的对象/实例。对象是类的实例化/具体化。

    比如:人一般都有姓名、性别、年龄等一些特征,还有睡觉等行为。我们就可以进行如下的操作:

public class PersonDemo{
  public static void main(String[] args){
    Person p = new Person();
    p.name = "rose";
    p.age = 18;
    p.gender = '女';
  }
}
calss Person{
  String name;
  int age;
  char gender;
  public void sleep(){
    System.out.println("sleep !");
  }
}

3、对象在内存中的存储

    对象在内存中的存储如下图:

public class PersonDemo{
  public static void main(String[] args){
    Person p = new Person();
    p.name = "翠花";
    p.age = 18;
    p.gender = '女';
    changeName(p);
    System.out.println(p.name);
    //结果是如花。
  }
  Public void changeName(Person p2){
    P2.name = "如花";
  }
}

    注意:对象在传值的时候传递的是地址。上个章节我们已经强调过。

    内存调用如下图:

 

4、成员变量和局部变量

    在类内方法外的变量叫成员变量。

    在方法内的变量叫局部变量。

    在定义格式上相同。

1.区别

1>定义位置不同

    成员变量是定义在类内方法外;局部变量是定义在方法或者语句内部。

2>作用域不同

    成员变量作用域整个类;局部变量只能在定义的方法或者语句内部使用。

3>内存存储位置不同

    成员变量存在堆内存中,并且在堆内存中自动的赋予默认值;局部变量是存储在栈内存中,不会自动给值,需要手动初始化。

4>生命周期不同

    成员变量是随着对象的创建而加载到堆内存中,并获取默认值,随着对象的回收而释放(解析);局部变量在方法或者语句执行的时候创建,随着方法或者语句的结束而立即移除出栈内存。

5、构造方法(constructor method)

1.定义

    在类中与类同名,没有返回值,也没有返回值类型的方法,主要是用于创建对象(描述对象创建过程)叫做构造方法,也叫构造函数。

    如果一个类没有手动提供构造函数,那么JVM在编译的时候会添加一个无参的构造函数。如果手动添加了构造函数,JVM就不会再提供无参构造函数。

class Person{
  public Person(){}
}

    构造函数在类的对象创建时就运行,一个对象创建后,其构造函数只执行一次,就是创建时执行。父类中必须有一个无参的构造函数,子类中可以有有参的也可以有无参的不用上下对应。

2.格式

public 类名(参数1,参数2,……){
  Code;
}

3.特点

    1.构造方法没有返回值类型,也没有返回值。

    2.构造方法可以重载。

    3.构造方法可以写return语句,为了规避风险。

    4.构造方法可以有参数,参数一般是创建对象必须依赖的条件(前提条件)。

    5.构造方法可以存在与类同名的普通函数。但是一般不建议使用。

    我将这5个特点简单记忆为1个没有,4个可以。

4.作用

1>创建对象

    任何一个对象创建时,都需要初始化才能使用,所以任何类想要创建实例对象就必须具有构造函数。标识对象创建的开始和结束。

2>对象初始化

    构造函数可以对对象进行初始化,并且是给与之格式(参数列表)相符合的对象初始化,是具有一定针对性的初始化函数。

6、this关键字

    this代表当前对象的引用。

    注意:在Java中所有的非静态属性和非静态方法都会通过对象来调用的。

1.作用

    this代表当前在使用的对象。

    可以认为是一个虚拟对象,可以通过this在本类中调用本类的非静态方法和非静态属性。

2.this语句

    this语句表示在本类的构造函数中调用本类的其他的对应形式的构造函数。

    this语句会自动匹配对应形式的构造函数。

    this语句必须放在构造函数的第一行。

class Person{
  public Person(){}
  public Person(String name,int age){
    this.name = name;
    this.age = age;
  }
  public Person(String name,int age,int gender){
    this(name,age);	//this语句。调用本身的构造函数。
    this.gender = gender;
  }
}

3.应用

    1.引用成员变量。

    2.调用类的构造方法。

    3.返回对象的值。return this;

7、匿名对象

1.定义

    没有名字的对象(匿名对象其实就是定义对象的简写格式)。

//正常形式
Car c =new Car();
c.run();
//匿名对象形式:
new Car().run();

2.使用方法

    1.当对象对方法仅进行一次调用的时候,就可以简化成匿名对象。

new Person.eat();
new Person.age = 20;

2.匿名对象可以作为实际参数进行传递。

changeAge(new Person);

 

8、代码块(code block)

1.局部代码块

1>定义

    在函数或者语句内部用{ }括起来的代码块称之为局部代码块,又叫普通代码块。是作用在方法中的代码块。

Public static void main(String[] args){
 {
  Int i = 2;
  System.out.println(i);
 }	//i 变量被释放。
  Int j = 3;
  System.out.println(j);
}
2>作用

    用于限制变量的使用范围和生命周期,从而提高内存的利用率。

2.构造代码块(constructional code block)

1>定义

    直接在类中定义且没有加static关键字的代码块称为构造代码块,也叫初始化代码块。在构造函数执行之前先执行一次。

    构造代码块在创建对象时被调用,每次创建对象都会被调用,并且构造代码块的执行次序优先于类构造方法。

    执行顺序:(优先级从高到低)静态代码块→main方法→构造代码块→构造方法。

2>格式
{
  构造代码块执行语句
}
3>作用

    把多个构造方法的共同代码放在一起。

4>构造代码块和构造函数的区别

    构造代码块是给所有对象进行统一初始化,而构造函数是给队形的对象初始化,因为构造函数是可以多个的,运行哪个构造函数就会建立相应的对象,但无论建立哪个对象,都会先执行相同的构造代码块。也就是说,构造代码块中定义的是不同对象共性的初始化内容。

二、面向对象的特征

    面向对象的特征有:封装、继承、多态 (抽象)。

1、封装(encapsulation)

1.定义

    封装是面向对象方法的重要原则,就是把对象的属性和操作(或服务)结合为一个独立的整体,并尽可能隐藏对象的内部实现细节。封装是一种信息隐藏技术。

2.体现形式

1>方法

    提高了代码的复用性。

2>属性的私有化

    属性的私有化属于类的封装,提高了代码的安全性。通过将属性私有化,然后提供对外的公共的访问方法来设置或者获取该属性,可以在方法中对属性的设置或者获取做一系列的限定。

3>内部类

    内部类也是封装的一种体现形式。

3.优点

    提高了复用性、安全性、使代码结构更加紧密。

    1.使属性私有化---隐藏信息,实现细节。

    2.使属性值更符合要求---可以对成员进行更精确的控制。

    3.提高了代码的安全性---类内部的结构可以自由修改

    4.良好的封装能够减少耦合。

2、继承(inherit)

1.定义

    如果一些类中含有相同的属性和方法,那么可以将这些相同的属性和方法提取到一个新的类中,利用extends关键字让原来的类和新的类产生联系,而这个关系称之为继承。新产生的类称之为父类(超类/基类),原来的类称之为子类(派生类)。

    父类是子类的一般化,子类是父类的具体化。

    注意:Java中支持的使单继承。一个子类只能有一个父类。一个父类可以有多个子类。

    子类通过继承父类可以使用父类中的一些方法和属性。

2.格式

calss a{}
class B extends A{//B类继承了A类
}

3.特征

    1.继承关系是传递的。

    2.继承简化了人们对事物的认识和描述,能清晰的体现相关类间的层次结构关系。

    3.继承提供了软件复用功能。

    4.继承通过增强一致性来减少模块间的接口和界面,大大增加了程序的易维护性。

    5.提供了多重继承机制。通过使用接口机制来实现多重继承。

4.优点

    1.提高复用性。

    2.提高安全性。

    3.统一结构。

5.使用条件

    1.子类拥有父类非private的属性和方法。

    2.子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。

    3.子类可以用自己的方法实现父类的方法。

6.缺陷

    1.父类变,子类就必须变。

    2.继承破坏了封装,对于父类而言,它的实现细节对于子类来说都是透明的。

    3.继承是一种强耦合关系。

7.单继承和多继承的优劣性比较:

    1.多继承在代码的复用性上要优于单继承,但是存在方法调用的混乱。

class A{
  public int m(){
    return 2;
  }
}
class B {
  public int m(){
    return 1;
  }
}
public class C extends A, B{
  C c = new C();
  int i = c.m(); // 多继承会产生方法调用的混乱
}

    2.单继承也可以提高代码的复用性,可以避免方法调用的混乱,提高了方法调用的安全性。

8.权限修饰符

    权限修饰符用于限定变量或者方法的使用范围。

    修饰符的控制范围:

 

本类中

同包类中

子类中

其他类中

Public(公共的)

可以

可以

可以

可以

Protected(受保护的)

可以

可以

可以

不可以

默认

可以

可以

同包子类可以

不可以

Private(私有)

可以

不可以

不可以

不可以

    权限修饰符的控制范围从定义的位置上看起。

package cn.a;
import cn.a.A;
public class extends A{
  public static void main(String[] args){
    B b =new B();
    b.m();//m方法使属于b对象,m方法没有在对象对应的子类中用。
  }
}

9.super关键字

    在创建子类对象的时候,会先创建一个父类对象,而这个父类对象在子类中以super关键字的形式存在。super是父类对象的引用。

    super表示在子类中代表了父类的对象。通过super来调用父类中的方法或者属性。可以将super看成一个虚拟对象。

1>super语句

    在子类构造函数中通过调用父类对应形式的构造函数。

    如果子类构造函数中没有手动添加,那么JVM在编译的时候会自动添加一个无参的super();。

    调用super语句的时候,会自动匹配父类中对应形式的构造函数。

    如果父类中没有提供无参构造函数,则默认省略的super语句就不能使用,那么这个时候子类的构造函数中需要手动添加一个super语句,super语句必须放在子类构造函数的首行。

    this语句和super语句不能同时使用,如果子类的构造函数中已经存在来this语句,它会调用本身的其他含有super语句的的构造函数,来创建父类。

    子类的构造函数中必然直接或者简介的有一个super语句,在创建子类对象的时候必然先创建一个父类对象。

    可以通过this来调用父类中的方法或者属性。

// 父类
class Pet {
	String species;
	int age;
	public Pet(int age) {
		this.age = age;
	}
	public Pet(String species, int age){		
	}
	public void eat() {
		System.out.println("在吃食~~~");
	}
}
// 通过extends关键字产生的联系---继承
// 子类
class Cat extends Pet {	
	public Cat(){
		// super语句必须放在构造函数的首行
		super(5);
	}
	// 方法的重写/覆盖
	@Override // 注解---这个注解用于标识这个方法是一个重写的方法
	public void eat() {
		System.out.println("猫在吃土~~~");
	}
}
class Dog extends Pet {
	public Dog() {
		// super语句---表示调用了父类的无参构造
		// super();
		super(5);
	}
	public void sleep() {
		// super 代表一个父类对象---在子类中调用父类中的方法或者属性
		super.eat();
		System.out.println("吃饱之后开始睡觉~~~");
	}
}
2>用法

    1.super.成员变量/super.成员方法;

    用来在子类中调用父类的同名成员变量或者方法。

    2.super(parameter1,parameter2……);

    用在子类的构造器中显示调用父类的构造器。

10.父类中不能被子类继承的东西

    1.构造方法。

    2.用private修饰的东西,即所有私有的东西。

    3.构造代码块和静态代码块。

    4.默认权限不同包的东西。

3、多态(Polymorphism)

1.定义

    多态是指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。多态主要针对对象的行为即方法,而不是对象的属性。

2.动态绑定(dynamicbinding)

    实现多态的技术称为动态绑定,是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。

3.作用

    降低模块与模块之间的依赖性就是解耦。

    多态的产生使为了解耦,消除类型之间的耦合关系。

4.必要条件

    1.要有继承。

    2.要有重写。

    3.父类引用指向子类对象。

5.优点

    1.可替换性(substitutability)。多态对已经存在代码具有可替换性。

    2.可扩充性(extensibility)。多态对代码具有可扩充性。

    3.接口性(interface-ability)。

    4.灵活性(flexibility)。在应用中体现了灵活多向的操作,提高了使用效率。配合反射实现解耦。

    5.简化性(simplictiy)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

6.体现形式

1>编译时多态

    在编译时期就要动态绑定的运行过程。例如:方法的重载。

add(1,2)
add(1,2,3)
//编译时期就能确定要使用的方法。
2>运行时多态

    在运行时期才能确定绑定的运行过程。例如:向上造型、方法的重写。

    继承是运行时多态的前提。

向上造型

1)定义

    用父类声明的,用子类来创建实际对象叫向上造型。

    子类的对象可以向上造型为父类的类型。即父类引用子类对象,这种方式被称为向上造型。

    使用向上造型声明的对象可以使用父类中的所有,但是只能使用子类中,父子类共有的东西。

    当向上造型创建对象的时候,用父类声明,用子类创建,父类在声明的时候就相当于给来这个对象一份提纲;子类创建对象的时候是告诉来对象该怎么干。

    当用向上造型来创建对象的时候,对象能够干什么,看的是父类。行为应该怎么干,看的是子类。

    当用向上造型来创建对象的时候,在编译的时候只检查两个类之间是否是继承关系,而不去具体检查是用哪个类来创建的对象,在运行时期才会检查是谁来创建的对象。所以,向上造型使运行使多态。

方法的重写

    当调用方法的时候,调用的是重写之后的方法。

    在编译的时候只需要检查这个声明的类中是否包含指定的方法,在运行的时候才绑定子类中的具体的方法。父类强转换为子类会出现ClassCastExcepion(类转换异常)。

3>对象多态

    向上造型

4>行为多态

    重写和重载

 

三、静态static

    static本身是一个修饰符,可以修饰变量、方法、内部类、代码块。静态是从类的层面来看的,已经超越了对象。

1、特点

    标记一个方法为static,意味着这个方法被所在类的所有实例公用,在类装载时初始化,被所有该类的实例共享,同时意味着:

    1.static方法内部不能声明static变量。

    2.Static方法不能被子类重写为非static方法。

    3.父类的非static方法不能被子类重写为static方法。

    4.Static代码块可以用static{}来完成,在类被第一次装载时执行初始化,先于静态方法和其他方法的执行。

2、静态内存流程

    程序启动的时候先通过类加载器(ClassLoader)将基本核心类库(java.long包)加载到方法区,其次是主函数所在的类加载到方法区。

    加载主函数所在的类。首先将Java源文件编译为class文件,然后class文件通过类加载器(ClassLoader)将class文件加载到方法区当中。将StaticDemo1.class存放到方法区中,将主函数main存放到方法区的静态区中。

    当执行语句Person p1 = new Person(); 时,会将Person类的java源文件编译成class文件,然后将class文件通过类加载器(ClassLoader)将class文件加载到方法区中。在静态常量池中开辟空间,将Person.class以及其包含的内容存放在静态常量池,然后在静态区中开辟空间,将Person.class中的静态属性以及静态方法存放到静态区中,并给静态属性变量赋予默认值(gender = ‘\u0000’)和方法区空间地址(0x02da)。以上工作完成之后,会在栈内存中声明一个对象p1。然后执行new Person,在堆内存中开辟空间存储p1对象的一系列属性(name,age,gender),并赋予默认值(name = null;age=0;gender = 0x02da;因为gender为静态变量所以gender的默认值是方法区中对应静态变量的空间地址)和堆内存空间地址(0x6f8d),然后将堆空间地址赋值给栈内存中对应的对象。

    当执行p1.name = “张无忌”;时,对象p1会沿着p1对象中存储的堆内存空间地址找到自己的属性,给自己的name属性赋值为:张无忌,将默认值覆盖。p1.age = 81;也是如此。

    当执行p1.gender = ‘男’;时,对象p1会沿着p1对象中存储的堆内存空间地址找到自己的属性gender,然后沿着gender中存储的方法区空间地址找到方法区中静态区里的gender,然后给静态区里的gender赋值为:男。

    当执行语句Person p2 = new Person();时,因为所有的类已经加载过了,所以可以直接进行声明和初始化操作。栈内存和堆内存中的操作和语句Person p1 = new Person();是一样的。

    当执行语句p2.name = “赵敏”; p2.age = 18 ; 过程和p1.name = “张无忌”; p1.age = 81 ; 是一样的。

    当执行p2.gender = ‘女’;时,对象p2会沿着p2对象中存储的堆空间地址找到堆内存中p2对应的gender属性,然后在根据gender属性中存放的地址找到方法区中静态区里的gender变量并赋值为:女,将原来的“男”值替换掉。由于p1和p2中gender属性存储的方法区空间地址是一样的,所以我们可以认为p1.gender = p2.gender = ‘女’;。

    当执行语句p1.eat();时,p1对象会调用方法区中静态常量池里Person.class的eat();方法,Person.class会给出eat()方法的地址,然后入栈,在栈内存中开辟空间执行eat();方法,eat();方法中会自动产生this关键字代表p1对象,此时this 中存储的使p1中存储的堆内存空间地址,然后输出方法的结果。

3、静态变量(static variable)

1.定义

    static修饰变量那么这个变量我们就称之为静态变量,又称为成员变量或者类变量。

2.特点

    静态变量随着类的加载而加载到了方法区中的静态区,并且在静态区中自动赋予了一个默认值。静态变量先于对象而存在,所以静态变量可以通过类名来调用,也可以通过对象来调用。该类产生的所有的对象实际上存的是该静态变量在静态区中的地址,静态变量是被所有对象所共享的。

    例如:System.in; System.out; 都是静态变量。

    1.静态变量有默认值。

    2.静态变量可以被类调用,也可以被对象调用。

    3.静态变量是被所有对象共享的。

    4.静态变量可以使用this来调用。

    5.静态变量不能定义到构造代码块中,但可以在构造代码块中对静态变量赋值。

    6.静态变量不能定义到方法中。静态变量在加载的时候就需要分配空间,而方法在加载的时候不需要空间,在执行的时候才需要内存空间。

    注意:实际开发中,static能少用就少用。

3.静态变量与实例变量的区别

    1.在语法定义上的区别。静态变量前要加static关键字,而实例变量前则不加。

    2.在程序运行时的区别。实例变量属于某个对象,必须创建对象才能使用。静态变量则可以直接使用类名引用。

 

4、静态方法(static method)

1.定义

    static修饰方法就叫静态方法,也叫类方法。

    Arrays.sort()、Arrays.toString()、Arrays.copyOf()、System.arraycopy()都是静态方法。

2.特点

    在类加载的时候加载到了方法区中的静态区,只是存储在静态区,在方法被调用的时候到栈内存中执行。静态区中的元素不归属于某一个对象而是归属于类。静态方法先于对象而存在的,所以静态方法可以通过类名来调用,也可以通过对象来调用。

    1.静态方法中不能定义静态变量,但可以对静态变量赋值。

    2.不能在静态方法中直接调用本类中的非静态方法。可以通过创建对象来调用。所有非静态的方法和变量都需要对象来调用。

    3.静态方法中不能使用this或者super。(主函数是静态方法)

    4.静态方法可以重载。

    5.静态方法不可以重写。但父子类中可以出现方法签名一致的静态方法,比如:main主函数。如果父子类中出现了两个方法签名的一致的方法要么全是静态,要么全是非静态。

    6.静态方法可以被继承。

    静态不属于对象。而是属于类。不依赖某个对象而存在,而是依赖于类存在的。类没有多态,多态针对的是方法

    注意:类只加载一次,是在第一次使用的时候才加载到方法区,而且加载到方法区中之后就不再移除了。

5、静态代码块(static code block)

1.定义

    在类中成员的位置用static修饰用{}括起来的代码块。

    静态代码块针对的是类,所以也可以叫做类代码块。

    实际上静态代码块是随着类的加载而加载到静态区,在类创建对象或者执行方法之前执行一次,终其一生只执行一次。

2.作用

    一般是对类进行初始化。

3.执行顺序

    在这个类第一次被真正使用(第一次创建对象/调用方法)的时候执行一次。如果一个类包含多个静态代码块,则按照书写顺序执行。由于类只在第一次使用的时候加载,所以静态代码块也只执行一次。

    代码执行顺序:先父类后子类,先静态后动态。(先父子类的静态,后父子类的动态)静态优先,父类优先。

    代码是从上到下,从左到右依次编译执行。

    创建子类对象的时候需要先创建父类对象→加载父类→执行父类静态代码块→执行子类代码块→父类构造代码块→父类构造函数→子类构造代码块→子类构造函数

四、final(最终的)

    final可以修饰数据,方法以及类。

1、常量(final variable)

1.定义

    当final修饰数据(基本类型和引用类型)的时候,表示这个变量的值不可变,称之为常量。终其一生只能赋值一次。

    在Java中所说的常量往往是指静态常量。因为实质上只有静态常量才是独有的一个。

    System.in/out in和out都是静态常量。NaN和infinity也是静态常量。

    arr.length length是个常量。

2.特点

    1.常量在定义好之后不可改变,final固定的是栈内存中的数值。

public class Demo {
  private final int i;

  public Demo(){
    this(5);
} 
  public Demo(int i){
    this.i = i; 
  }
}
Demo d = new Demo(5);

    2.常量可以作为参数传递。

    3.对引用类型而言,final固定的是其在栈中的地址不可变。

    数组在栈内存中存储的是地址,用final修饰,是不能改变数组的地址,但数组的值可以改变。对于对象而言,对象的引用不能改变,但是引用的属性值是可以进行改变的。

    4.成员常量只要是在对象创建完成之前(构造方法/函数执行结束之前)赋初始值即可。

    5.静态成员常量(static final)只要在类加载完成之前给值即可,而且只能在静态代码块中赋值。

2、最终方法

1.定义

    final修饰方法的时候,这个方法就是最终方法。

2.特点

    1.最终方法不可以被重写,可以重载,可以被继承。

    2.静态方法可以被final修饰。

3、最终类

1.定义

    final修饰类那么这个类就是最终类。

2.特点

    1.最终类不可以被继承,也不能有匿名内部类形式。

    2.现阶段最终类的方法不能被重写。

    System 、String是最终类。

五、abstract(抽象的)

abstract class Pet{
  public abstract void eat();
}
class cat extends pet{
  public void eat(){
    System.out.println("这只猫在吃鱼……")
  }
}

1、抽象方法(abstract method)

1.定义

    如果所有的子类中存在了一些名称一致而细节不同的方法的时候,这个时候可以在父类中声明该行为,此时声明行为的时候不需要添加方法体,所以此时该方法就形成了抽象方法,使用abstract修饰。

2.特点

    1.抽象方法可以和抽象方法重载,也可以和实体方法重载。

    2.抽象方法没有方法体。

3.修饰权限

    1.抽象方法不可以被static、final、private修饰,因为final和private修饰符修饰的方法都不可以被重写;static修饰的方法,先于对象存在,没有具体对象没办法加载。

    2.抽象方法可以使用默认权限修饰,要求子类必须和父类同包。

    3.抽象方法可以被protected权限修饰,要求要么同包要么是子类。

2、抽象类(abstract class)

1.定义

    将一些名称一致但是细节不同的行为提取到父类中定义为抽象方法,抽象方法所在的类就是抽象类,用abstract来修饰的类。抽象类中,不一定含有抽象方法,但是抽象方法所在的类一定是抽象类。

2.特点

    1.抽象类不可以在Java中创建对象/实例化。即使没有抽象方法也无法创建对象,可以创建匿名内部类。

    2.抽象类有构造方法。抽象类的构造方法可以私有化,在本类中使用。可以创建对象,在底层用C语言创建对象。抽象类的构造方法一旦被私有化,就不能被继承了。

    3.抽象类被子类继承之后,必须重写其中的抽象方法。子类如果也为抽象类,可以不重写。抽象方法必然会被重写。

    4.抽象类中可以没有抽象方法。抽象类中可以定义一切的属性和方法。

    5.抽象方法不能有方法体,()之后直接以;结尾。

 

3.修饰权限

    抽象类不能用final修饰。最终类不可以是抽象类。

4.作用

    限制规定子类必须实现某些方法,但不关注实现细节。

5.抽象类和普通类的区别

    抽象类和普通类的区别就是可以有抽象方法,不可以创建对象。

六、接口(interface)

1、定义

    用interface来声明,所有方法都为抽象方法那么我们就称之为接口。通过implements关键字让接口和类产生联系,这个过程叫实现。在接口中使用向上造型来创建对象,就是接口的多态。

interface Pet{
  void eat();
}
public class Mouse implements Pet{
  public void eat(){}
}

2、特点

    1.接口中方法的abstract关键字可以省略。

    2.类用implements来实现一个接口。必须实现这个接口中所有的方法。

    3.由于接口中都是抽象方法,接口不能实例化。

    4.接口中没有构造函数。虽然接口在编译完成之后会产生class文件,但是接口不是类。

    5.接口中可以定义属性,这个属性默认是一个静态常量。

3、权限修饰

    1.接口中的属性默认是用public static final 来修饰,修饰符的位置可以互换。

    2.接口中的方法默认用public abstract修饰,而且只能是public修饰的,public可以省略不写。在接口的子类中实现接口的方法记得用public修饰。

interface A {
  void m(); // 默认是public修饰
}
public class B implements A {
  void m(){} // 需要添加修饰符public
}

4、继承(extends)与实现(implements)

    Java中类支持单继承,多实现。一个类只能继承一个类,但是一个类可以实现多个接口。一旦出现了多实现,那就必不可免的会导致方法调用混乱。

interface Pet{
  Void eat();
}
interface Animal{
  Void play();
}
public class Mouse implements Pet,Animal{
  public void eat(){}
  public void play(){}
}

    Java中接口之间是多继承,并且接口和类之间是多实现的关系,所以就形成了一张继承关系网,由于在网状结构中寻找一个根节点比较困难,为了提高效率,Java在编译的时候放弃检查接口和类之间是否有实现关系。

    当类进行强制转换的时候,JVM在编译的时候会对两个类进行检查,检查这两个类之间是否有继承关系。如果有继承关系,则编译的时候会通过,但是运行的时候不一定正确。如果没有继承关系,则在编译的时候直接报错。

5、作用

    统一了结构。接口可以作为模板,配合多态实现解耦,比如:反射。

七、内部类

1、定义

    定义在类或者接口中的类就称之为内部类。内部类是封装的第三种形式。

2、分类

    内部类根据使用的位置和修饰符不同分为:方法内部类、成员内部类、静态内部类、匿名内部类。

3、特点

    除了静态内部类,其余的内部类中都不允许定义静态属性和静态方法,但是可以定义静态常量。

    除了静态内部类,其余的内部类都可以使用当前外部类的属性和方法,但是静态内部类只能使用外部类的静态成员。

4、方法内部类

1.定义

    定义在方法中的类叫做方法内部类。

class Outer1{
  public void m(){
   class Inner1{
    public void m(){
     System.out.println(“inner1 m”);
     }  
    }
    Inner i1 = new Inner1();
    i1.m();
    System.out.println(“outer1 m”);
  }
}

2.特点

    1.方法内部类在哪定义在哪使用。除了当前的方法,其余地方不能使用。

    2.方法内部类优先于当前方法加载。

    3.方法内部类不允许使用当前方法的局部变量。可以使用当前方法的常量。在JDK1.8中常量不用显式声明常量,但是本质上依然是一个常量。

    4.方法内部类可以使用外部类的一切属性。

    5.方法内部类中可以定义成员方法、成员属性和静态常量,但是不能定义静态方法和静态属性。

3.作用

    为什么要定义方法内部类?

    方法内部类是为了私有本类方法中的参数。内部类可以继承可以实现。

5、成员内部类

1.定义

    定义在类内方法外的类叫做成员内部类。也就是成员变量的位置。利用外部类对象来创建成员内部类对象。

public class InnerClassDemo {
	public static void main(String[] args) {		
		new Outer2().new Inner2().m();	//利用外部类对象来创建成员内部类对象
	}
}
class Outer2{
	int i=5;
	class Inner2{
		public void m(){
			System.out.println("inner2 m");
		}
	}
}

2.特点

    1.成员内部类可以定义普通的方法和属性,但是依然不能定义静态方法和静态属性。

    2.成员内部类可以定义静态常量。

    3.成员内部类可以使用外部类中的一切方法和属性。

    4.成员内部类可以使用权限修饰符修饰内部类。

    5.成员内部类可以创建对象。

    Java底层集合和映射用的比较多。有一系列对象,而这些对象对外不可见,就可以用成员内部类。

 

6、静态内部类

1.定义

    用static修饰的成员内部类叫做静态内部类。可以直接利用外部类来创建静态内部类的对象。

2.特点

    1.可以定义一切的属性和实体方法。

    2.静态内部类只能使用外部类中的静态属性和静态方法。非静态的属性和方法不可用。

    3.可以使用权限修饰符修饰。

7、匿名内部类

1.定义

    没有名字的内部类叫做匿名内部类。包含成员匿名内部类,方法匿名内部类。

2.特点

    1.匿名内部类本质上是继承了对应的类或者是实现了对应的接口。

    2.只要一个类可以被继承,那么这个类就可以出现匿名内部类的形式。当利用一个类来创建一个匿名内部类的时候,实际上这个匿名匿名内部类是继承了这个类。

    3.匿名内部类有构造函数,但是不能手动添加构造方法。

    当利用匿名内部类来创建对象的时候,要求这个匿名内部类必须实现父类中的所有抽象方法。

Demo demo = new Demo() {//声明一个匿名内部类
			@Override
			public void m() {
			}
		};
		// 匿名内部类本质上是实现了这个接口
		A a = new A() {
		};
		// B b = new B() {
		// };
	}

    4.如果匿名内部类定义到了方法中,此时匿名内部类的使用规则和方法内部类一致。

    5.如果匿名内部类定义到了类中,此时匿名内部类的使用规则和成员内部类一致。

八、内部接口

1、定义

    定义在类或者接口中的接口叫做内部接口。

2、特点

    类中定义的接口、接口中定义的类或者是接口默认都是用static修饰。

    接口必然要被实现,如果内部接口不是静态的,这个时候就需要一个外部类对象来调用接口,而在声明类实现这个接口的时候,无法创建对象,无法创建对象就无法实现了。

package cn.tedu.innerclass;
public class InnerDemo2 implements Outer1.Inner1 {
	@SuppressWarnings("unused")
	public static void main(String[] args) {
		Outer2.Inner2 oi2 = new Outer2.Inner2();
	}
}
class Outer1 {
	// 内部接口
	// 这个接口默认是用static修饰
	interface Inner1 {
	}
}
interface Outer2 {
	// 内部类
	// 默认是用static修饰
	class Inner2 {
	}	
	interface Inner3 {		
	}
}

九、

1、声明语句

    声明包用的package,包的产生是为了解决同名文件的问题。

    声明格式如下:

package m.n.c

    一个Java文件中只允许存在一个package语句,而且这个package语句必须放在整个Java文件的首行。

2、导包语句

    导入包用的是import。

import java.util.* //表示导入util包下的所有的类而不包括子包下的类。
//*是一个通配符。

3、分类

    java.lang:核心包(核心类库),在程序启动的时候就已经加载到了方法区中了,在使用的时候不需要导包。

    java.util —— 工具包,存放了一系列简化操作的工具类。

    java.io —— 数据传输。

    java.nio —— 高并发。

    java.net —— 网络传输。

    java.math —— 数学运算。

    java.sql —— 数据库。

    java.awt —— 图形用户界面。(几乎不用)

    java.security —— 数据安全。

    java.text —— 格式化。

    javax.* —— 扩展包。

    org.* —— 第三方厂商和开源社区提供的包。

    同包类和java.lang包不用写导包语句。

    注意:包名不能以java,javax,org开头

 

    以上为个人学习整理的笔记和心得,于大家分享,希望大家多批评斧正。

上一篇:JAVA基础知识

下一篇:Java API:Object class

转载于:https://my.oschina.net/u/3754001/blog/1801097

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值