面向对象编程–类与对象
面向对象的三大特征
封装性
所谓封装,就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的类或者对象进行信息隐藏。简而言之,就是内部操作对外部而言不可见。
使用private关键字实现的封装处理只是封装的第一步,其最大的特征就是只允许本类访问,而不允许外部类访问。要想访问私有属性,按照java的设计原则,必须提供以下两种方法:
getter主要用于进行属性内容的获取;
setter主要用于属性内容的修改和设置。
继承性
继承是指这样一种能力:他可以使用现有类的所有功能,并且在无需重新编写原来类的情况下对这些功能进行扩展。
多态性
所谓多态就是指一个类实例的相同方法在不同情形下的不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。
类的设计原则
编写类时,类中的所有属性必须使用Private封装;属性若要被外部访问,必须定义setter, getter方法。
构造方法
所谓的构造方法就是使用关键字new实例化新对象时进行调用的操作方法。对于构造方法的定义,需要遵循:
(1)方法名必须与类名相同;
(2)构造方法没有返回值类型声明;这个是为什么呢?首先类的组成有:属性(在对象开辟堆内存时开辟的空间)、构造方法(是在使用New之后调用的)、普通方法(在空间开辟了,构造方法执行之后可以多次调用的)。编译器是根据程序结构来区分普通方法和构造方法的,所以在构造方法前没有返回值类型声明;
(3)每个类中至少存在一个构造方法,若没有明确的规定,则系统自动生成一个无参构造。若类中定义了构造方法,则默认的无参构造将不再生成。
this关键字
有三个方面的用途:调用本类方法(一种是调用普通方法this.方法名(参数)一种是调用构造方法this(参数)此时应该注意:调用构造方法的语句应该放在构造方法首行,并且需要留有出口)、调用本类属性(当参数与类中属性同名时,类中属性无法被正确赋值,此时加上该关键字便可以正确给对象属性赋值)、表示当前对象。
static关键字
(1)访问static属性(类属性)应使用类名称.属性名;
(2)所有的非static属性(实例变量)必须在对象实例化后使用,而static属性(类属性)不受对象实例化控制;
(3)一般情况下都不会使用static属性,但是若要描述共享属性的概念,或者不受对象实例化控制,就要使用static;
(4)使用static定义的方法时,直接通过类名称访问;
(5)所有的static方法不允许调用非static定义的属性或定义;
(6)所有的非static方法允许访问static属性;
总而言之,使用static属性的目的只有一个:某些方法不希望受到对象的控制,即可以在没有实例化对象的时候执行。
代码块
使用{}定义的一段代码。根据代码块的位置以及关键字,代码块可以分为四种:普通代码块(直接使用{}定义)、构造块(定义在类中,不加任何修饰符)、静态块(使用static定义的代码块)、同步代码块。看代码:
public class HelloA{
//构造方法
public HelloA(){
System.out.println("Hello A!构造方法");
}
//非静态代码块
{
System.out.println("not static A class.非静态代码块");
}
//静态代码块
static{
System.out.println("static A.静态代码块");
}
}
public class HelloB extends HelloA{
//构造方法
public HelloB(){
System.out.println("Hello B!构造方法");
}
//非静态代码块
{
System.out.println("not static B class.非静态代码块");
}
//静态代码块
static{
System.out.println("static B.静态代码块");
}
}
public class Test4{
public static void main(String[] args){
System.out.println("------start------");
new HelloB();
System.out.println("-------end-------");
}
}
看结果:
D:\MySQL5.7\javawork>java Test4
------start------
static A.静态代码块
static B.静态代码块
not static A class.非静态代码块
Hello A!构造方法
not static B class.非静态代码块
Hello B!构造方法
-------end-------
我们可以发现,构造块(定义在类中的代码块)优先于构造方法执行,每产生一个新的对象,就调用一次构造块,构造块可以进行简单的逻辑操作。继续看代码:HelloA与HelloB不变,改动Test4,再加一个实例化对象:
public class Test4{
public static void main(String[] args){
System.out.println("------start------");
new HelloB();
new HelloB();
System.out.println("-------end-------");
}
}
看结果:
D:\MySQL5.7\javawork>java Test4
------start------
static A.静态代码块
static B.静态代码块
not static A class.非静态代码块
Hello A!构造方法
not static B class.非静态代码块
Hello B!构造方法
not static A class.非静态代码块
Hello A!构造方法
not static B class.非静态代码块
Hello B!构造方法
-------end-------
我们可以发现,静态代码块优先于构造块执行,并且无论产生多少实例化对象,静态块只执行一次。若在主类中定义静态块,则优先于主方法(main())执行。
内部类
所谓的内部类简单理解就是在一个类的内部进行其它类结构的嵌套操作。看代码:
public class Test5{
public static void main(String[] args){
Outer out = new Outer();
out.fun();
}
}
//外部类
class Outer{
private String msg = "Hello world!";
//定义一个内部类
class Inner{
public void print(){
System.out.println(msg);//内部类的打印方法
}
}
//外部类中定义了一个fun方法
public void fun(){
Inner in = new Inner();//内部类对象
in.print();//内部类提供的打印方法
}
}
D:\MySQL5.7\javawork>java Test5
Hello world!
这就是一个内部类的例子。看着程序的结构比较混乱,但是却内部类可以方便的操作外部类的私有访问。为什么会存在内部类呢?
(1)内部类方法可以访问该类定义所在作用域中的数据,包括被private修饰的私有数据;
(2)内部类可以对同一包中的其他类隐藏起来并且可以实现Java单继承的缺陷;
(3)当我们想要定义一个回调函数却不想写大量代码的时候我们可以选择使用匿名内部类来实现。
内部类与外部类的关系
(1)对于非静态内部类,内部类的创建依赖外部类的实例对象,在没有外部类实例之前是无法创建内部类的;
(2)内部类是一个相对独立的实体,内部类可以直接访问外部类的元素,但是反之不行;外部类只能通过内部类引用间接访问内部类元素。
内部类分类
在java中,内部类主要有:成员内部类(不能存放任何的static变量和方法、成员内部是依附于外围类的,只有先创建了外部类才能创建内部类)、静态内部类(其创建不需要依赖外围类的创建,不可以使用任何外围类的非static成员变量和方法,而内部类则可以)、方法内部类(定义在外部类的方法中,方法内部类只能在该方法中被使用出了该方法就会失效)、匿名内部类(没有名字的方法内部类,符合方法内部类的所有约束,除此以外,匿名内部类没有访问修饰符、必须继承一个抽象类或实现一个接口、不能存在任何静态成员或方法、没有构造方法,没有类名、与局部内部相同匿名内部类也可以引用方法形参(此形参声明为final))。
继承的定义与使用
extends: 继承的主要作用在于在已有的基础上继续进行功能的扩充,即可以消除在结构定义上的重复。看代码:
class Person{
private String name;
private int age;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
}
class Student{
private String name;
private int age;
private String school;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
public String getSchool(){
return school;
}
public void setSchool(String school){
this.school = school;
}
}
public class Test7{
public static void main(String[] args){
Student student = new Student();
student.setName("steven");
student.setAge(20);
System.out.println("姓名:"+student.getName()+" 年龄:"+student.getAge());
}
}
大量的重复代码,但是如果用继承的话,就会消除这种情况,如下:
class Person{
private String name;
private int age;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
}
class Student extends Person{
}
public class Test7{
public static void main(String[] args){
Student student = new Student();
student.setName("steven");
student.setAge(20);
System.out.println("姓名:"+student.getName()+" 年龄:"+student.getAge());
}
}
结果一样。
D:\MySQL5.7\javawork>java Test7
姓名:steven 年龄:20
当然继承也是有限制的,子类对象在进行实例化之前一定会首先实例化父类对象,默认调用父类的构造方法之后再调用子类构造方法进行子类对象初始化。实际上,在子类的构造方法中相当于隐含了一个语句super();如果父类里没有提供无参构造,则此时必须使用super()指出你要调用的父类构造方法。在继承中,java只允许单继承,不允许多重继承,但是可以多层继承,即一个子类只能继承一个父类。
总结如下:
(1)继承可以扩展已有类的功能,消除代码重复;
(2)不管如何操作,一定要先实例化父类对象;
(3)不允许多重继承,但允许多层继承。
覆写(override)
如果子类定义了与父类相同的方法或属性的时候,这样的操作就叫覆写。
方法的覆写
子类定义了与父类方法名称、参数类型及个数完全相同的方法。但是覆写不能够拥有比父类更为严格的访问控制权限。看代码:
public class Test8{
public static void main(String[] args){
new Student().print();
}
}
class Student extends Person{
public void print(){
System.out.println("student的print方法");
}
}
class Person{
public void print(){
System.out.println("person的print方法");
}
}
D:\MySQL5.7\javawork>java Test8
student的print方法
覆写时注意:
(1)当前使用的对象是通过哪个类new的;
(2)当调用了某个方法,如果该方法被子类覆写过了,则调用的一定是被覆写过的方法;
(3)子类覆写父类是因为父类的方法功能不满足要求才覆写;
(4)方法覆写的时候使用的时public 权限。
重载与覆写的区别(非常重要)
(1)重载:方法名称相同,参数类型及个数不同;范围在一个类中;没有权限要求;
(2)覆写:方法名称、返回值类型、参数类型及个数完全相同;继承关系;被覆写的方法不能拥有比父类更严格的访问控制权限。
关键字 this 和 super 的区别 :
(1)this: 访问本类中的属性和方法;先查找本类,如果没有就调用父类;表示当前对象;
(2)super: 由子类访问父类中的属性和方法;不查找本类而直接调用父类。
final 关键字
在java中final称为终结器。
(1)使用该关键字修饰的类不能有子类;
(2)final成员变量必须在声明时初始化或在构造器中初始化,否则出错;
(3)final一旦修饰一个类,该类的所有方法都会默认加上final修饰(不包含成员变量);
(4)使用final定义的方法不能被子类覆写;
(5)使用final定义的变量就变成了常量,常量必须在声明时赋值,并且不能够被修改,常量全用大写字母,多个单词之间以下划线分割,且其定义的变量不能再次赋值。
多态性
多态性核心表现在两方面:
方法多态性
方法的重载:同一方法名可以根据参数的类型或个数调用不同的方法体;
方法的覆写:同一父类方法,可根据实例化子类的不同有不同实现;
对象多态性
对象的向上转型:父类 父类对象 = 子类实例最核心的用途:操作参数统一;
对象的向下转型:子类 子类对象 = (子类)父类实例将父类对象变为子类对象,需要子类扩充操作的时候需要向下转型;在向下转型之前先进行判断,而后进行转型,可以使用instanceof关键字,语法为子类对象 instanceof类,返回boolean类型
多态性小结:
(1)对象多态性的核心在于方法的覆写;
(2)通过对象的向上转型可以实现接收参数的统一,向下转型可以实现子类扩充方法的调用(一般不用向下转型,由安全隐患);
(3)两个没有关系的类对象是不能够进行转型的,一定会出错。
12万+

被折叠的 条评论
为什么被折叠?



