一、类的封装
1.类的封装定义
类的封装,是一种将一组相关的变量和函数封装成一个独立的数据类型的技术,以提高程序的可维护性、可重用性。
类的封装,可以将一组相关的变量和函数封装在一个独立的自定义数据类型内,这种独立的数据类型称为类,类是一种抽象,它可以把相关的信息和数据封装起来,便于维护和使用,从而提高程序的可维护性和可重用性。
2.类的封装特性
(1)数据封装
类的封装最大的优点之一是将数据和它们的操作封装在一个结构里面,使得数据操作更加简单、快捷。
(2)访问控制
类可以通过类的修饰符来控制访问权限,使得部分数据和函数只能被类本身所调用,这样可以保证自己的资源不被滥用。
(3)抽象
类能够把复杂的具体事物抽象成一个独立的实体,以便让程序进行更有效的管理。
(4)继承
类具有继承的能力,可以将相关的操作封装放到基类中,而子类只需要根据需要进行相应的改进和扩展,这样可以减少代码的见余,提高程序的可复用性。
3.this关键字
this关键字在java中表示当前类的对象,可以理解成指向对象本身的一个指针。通俗地说就是表示当前类对象”自己“,它是在对象被创建时自动产生的。我们可以用this关键字来调用本类的属性、方法、构造方法。当我们在构造方法中使用this时,this表示的是当前类的成员变量。从上所知,this关键字的作用有以下几点:
①用来表示当前类的对象;
②调用当前类中的属性;
③调用当前类的方法或构造方法。
4.构造方法
(1)构造方法的定义
构造方法,是一种特殊的方法,它是一个与类同名的方法。对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化。当类实例化一个对象时会自动调用构造方法。构造方法和其他方法一样也可以重载。
(2)构造方法的作用
①构造出来一个类的实例;
②对构造出来个一个类的实例(对象)初始化。
(3)构造方法的特殊性
构造方法是一种特殊的成员方法,它的特殊性反映在如下几个方面:
1.构造方法的名字必须与定义他的类名完全相同,没有返回类型,甚至连void也没有。
2.主要完成对象的初始化工作,构造方法的调用是在创建一个对象时使用new操作进行的。
3.类中必定有构造方法,若不写,系统自动添加无参构造方法。接口不允许被实例化,所以接口中没有构造方法。
4.不能被static、final、synchronized、abstract和native修饰。
5.构造方法在初始化对象时自动执行,一般不能显式地直接调用.当同一个类存在多个构造方法时,java编译系统会自动按照初始化时最后面括号的参数个数以及参数类型来自动一一对应。完成构造函数的调用。
6.构造方法分为两种:无参构造方法和有参构造方法。构造方法可以被重载,没有参数的构造方法称为默认构造方法,与一般的方法一样,构造方法可以进行任何活动,但是经常将他设计为进行各种初始化活动,比如初始化对象的属性。
7.构造代码块:
(1)作用:给对象进行初始化,对象一建立就执行,而且优先于构造函数执行;
(2)构造代码块和构造函数的区别:构造代码块是给所有不同对象的共性进行统一初始化,构造函数是给对应的对象进行初始化。
8.自定义类中,如果不写构造方法,java系统会默认添加一个无参的构造方法。如果写了一个有参的构造方法,就一定要写无参构造方法。
二、类的继承
1.什么是继承以及继承的作用
面向对象编程中有一个重要的思想叫继承,子类通过继承可以获得父类的属性和方法,被继承的类叫父类,继承的类叫子类。(注意:私有属性不能继承。)
作用:子类通过继承可以获得父类的属性和方法,提高开发的效率及代码的复用率。
2.继承如何表示
class 子类名(父类名):
pass
子类可以实现自己独有的方法;父类当中不能调用子类方法;python中的继承是单边继承,只能子类继承父类。
当子类和父类具有同样的方法或者属性的时候,父类还是用父类的,子类不再用父类的,而是用自己的。
3.重写父类方法
重写:就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法。
调用重名的父类方法:
方式一:父类名.方法名(self)
方式二:super().方法名()
super() 超继承:使用父类当中的方法;super()代表的就是父类中的对象
4.多重继承
一个子类可以同时继承多个父类。继承了多个父类,父类中的方法都可以使用
class SmartPhone:
pass
class Camera:
pass
class Recorder:
pass
class Iphone(SmartPhone, Camera, Recorder):pass
三、抽象类与接口
1.抽象类
抽象类不允许被实例化,只能被继承。
抽象类可以包含属性和方法。方法可以包含代码是吸纳,也可以不包含代码实现。不包含代码实现的方法叫抽象方法。
子类继承抽象类,必须实现抽象类中的所有抽象方法。
抽象类需要注意的地方:
1.抽象类和抽象方法都是使用abstract修饰的。
2.抽象类不能实例化,但是普通类是可以的。 3.抽象类当中不一定包含抽象方法,但是包含抽象方法的类一定是抽象类!
4.抽象类当中,可以定义成员变量和成员方法。
2.接口
接口不能包含属性(成员变量)。
接口只能声明方法,方法不能包含代码实现。
类实现接口的时候,必须实现接口中声明的所有方法。
接口需要注意的地方:
1.接口是使用interface来进行定义的。
2.接口当中,不能有实现的方法,但是有两种类型的方法需要注意:
(1)静态方法可以有具体实现。
(2)这个方法被dafault关键字修饰,也是可以的 。
3.接口当中的方法默认是public abstract修饰的。
4.接口当中的成员变量默认是:public static final修饰的。
四、类的多态
1.多态,是面向对象的程序设计语言最核心的特征。按字面的意思就是“多种状态”。是允许将子类类型的对象定义成父类类型的一种技术。多态是通过子类重写父类的方法来实现的。
2.多态是通过子类重写父类的方法来实现的。
3.多态性使得能够利用同一类型来引用不同类的对象,以及根据所引用对象的不同,以不同的方式执行相同的操作。
4.虽然子类被定义成父类类型,但是通过“父类对象.方法()”的方式,实际调用的还是子类的代码。这也说明了“父类类型”只是一个“傀儡”,真正发号施令还是子类。
5.如果子类,没有重写父类的方法,默认调用父类中的方法。
前提:有继承关系,且有方法的重写。
多态的作用:把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
五、类的高级特性
1.Static修饰符
static是静态修饰符,一般用于修饰类中的成员变量或者成员方法(也可修饰代码块,称之为静态代码块,后面会提到的),被修饰的成员属于类(注意:不是再是属于某个对象的。也就是说既然属于类,就可以不靠创建对象来调用了 ),可以通过类名直接访问类中的static修饰的成员变量或者static修饰的成员方法,static修饰的静态成员变量和静态成员方法被所在类的所有实例对象所共有。
(1) static修饰成员变量:
格式 :
static 数据类型 变量名;
例如 : static String name;
注意 :多个对象在访问static修饰的成员变量时,其中的一个对象将static成员变量值进行了修改,其他对象中的static成员变量值也随之改变,即多个对象共享同一个static成员变量
(2)static修饰成员方法:
格式 :
修饰符 static 返回值类型 方法名(参数列表){
执行语句;
return 返回值;
}
例如 :
public static void println( ){
System.out.println(" 你好");
}
2.Final修饰符
在Java中,final表示“最终的、不可改变的、完结的”,它也是一种修饰符,可以修饰变量、方法和类。final修饰变量、方法和类时的意义是不同的,但本质是一样的,都表示不可改变,final修饰的变量叫做最终变量,也就是常量,修饰的方法叫做最终方法,修饰的类叫做最终类。
根据修饰变量的作用范围,比如在修饰局部变量和成员变量时,final会有不同的特性:
● final修饰局部变量时,在使用之前必须被赋值一次才能使用;
● final修饰成员变量时,如果在声明时没有赋值,则叫做“空白final变量”,空白final变量必须在构造方法或静态代码块中进行初始化。
根据修饰变量的数据类型,比如在修饰基本类型和引用类型的变量时,final也有不同的特性:
● final修饰基本类型的变量时,不能把基本类型的值重新赋值,因此基本类型的变量值不能被改变。
● final修饰引用类型的变量时,final只会保证引用类型的变量所引用的地址不会改变,即保证该变量会一直引用同一个对象。因为引用类型的变量保存的仅仅是一个引用地址,所以final修饰引用类型的变量时,该变量会一直引用同一个对象,但这个对象本身的成员和数据是完全可以发生改变的。
final修饰变量时,常用的语法格式如下:
final String 变量名=变量值;
我们在使用final声明变量时,一般会要求变量名的单词全部大写,且变量名由多个单词组成时,多个单词之间用下划线“_”分隔开,比如“SCHOOL_NAME”。
3.代码块
(1)代码块概念以及分类
使用{}定义的一段代码称为代码块。根据代码块定义的位置以及关键字,又可以分为以下四种:
普通代码块
构造(实例)代码块
静态代码块
(2)普通代码块
普通代码块:定义在方法中的代码块
首先我们看下面这一段代码
/**
* Created with IntelliJ IDEA.
* Description: Hello,I would appreciate your comments~
* User:
* Date: -04-03
* Destination:普通块代码块
*/
public class TestDemo1 {
public static void main(String[] args) {
{//普通代码块直接用{}定义,
int x =10;
System.out.println("x1 = "+x);
}
int x = 200;
System.out.println("x2 = "+x);
{
int y = 300;
System.out.println("y = "+y);
}
}
}
这里的输出为:
x1 = 10 x2 = 200 y = 300
(3)构造(实例)代码块
构造块:定义在类中的代码块(不加修饰)。也叫:实例代码块。
构造代码块一般用于初始化实例成员变量
/**
* Created with IntelliJ IDEA.
* Description: Hello,I would appreciate your comments~
* User:
* Date: -04-03
* Destination:实例代码块
*/
public class Student {
private String name;
private String gender;
private int age;
private double score;
// 构造函数
public Student(){
System.out.println("Student的构造函数被执行了!");
}
// 实例代码块
{
this.name = "Bonnie";
this.age = 19;
this.gender = "女";
System.out.println("实例代码块初始化了!");
}
public void show(){
System.out.println("name:"+name+"age:"+age+"gender:"+gender);
}
public static void main(String[] args) {
Student s1 = new Student();
s1.show();
}
}
(4)静态代码块
使用static定义的代码块称为静态代码块。
一般用来初始化静态成员变量。
public class Student {
private String name;
private String gender;
private int age;
private double score;
private static String classRoom;
// 构造函数
public Student(){
System.out.println("Student的构造函数被执行了!");
}
// 实例代码块
{
this.name = "Bonnie";
this.age = 19;
this.gender = "女";
System.out.println("实例代码块初始化了!");
}
// 静态代码块
static {
classRoom = "三年二班";
System.out.println("静态代码块被调用了!");
}
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student();
System.out.println(Student.classRoom);
}
}
4.匿名对象
(1)匿名对象的创建
置名对象是指在创建对象时,只有创建对象的语句,却没有把对象地址赋值给某个变量,如:对于已存在的Person
①创建一个普通对象
Person P = new Person();
②创建一个匿名对象
new Person();
(2)匿名对象的特点
①创建匿名对象可以直接使用,没有变量名
new Person().work(); // work方法被一个没有名字的Person对象调用了
②匿名对象在没有指定其引用变量时,只能使用一次
new Person().work(); // 创建一个匿名对象,调用work方法
new Person().work(); // 想再次调用work方法,要重新创建一个匿名对象
③匿名对象可以作为方法接收的参数,方法返回值使用
class Demo {
public static person getperson(){
// 普通方式
// Person p=new Person();
// return p;
// 匿名对象作为方法返回值
return new Person();
}
public static void method(Person p){ }
}
class Test {
public static void main(string[] args){ // 调用getperson方法,得到一个Person对象 Person person=Demo.getperson(); // 调用method方法
Demo.method(person);
// 匿名对象作为方法接收的参数
Demo.method(new Person());
}
}
5.内部类
java内部类分为: 成员内部类、静态嵌套类、方法内部类、匿名内部类 。
(1)内部类的共性
①内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 。
②内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的 。
③内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的。
(2)成员内部类
class Outer {
class Inner{}
}
编译上述代码会产生两个文件:Outer.class和Outer$Inner.class。
(3)静态嵌套类
静态内部类中可以定义静态或者非静态的成员。
从技术上讲,静态嵌套类不属于内部类。因为内部类与外部类共享一种特殊关系,更确切地说是对实例的共享关系。而静态嵌套类则没有上述关系。它只是位置在另一个类的内部,因此也被称为顶级嵌套类。
静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。静态嵌套类仅能访问外部类的静态成员和方法。
class Outer{
static class Inner{}
}
class Test {
public static void main(String[] args){
Outer.Inner n = new Outer.Inner();
}
}
在静态方法中定义的内部类也是StaticNested Class,这时候不能在类前面加static关键字,静态方法中的StaticNested Class与普通方法中的内部类的应用方式很相似,它除了可以直接访问外部类中的static的成员变量,还可以访问静态方法中的局部变量,但是,该局部变量前必须加final修饰符。
(4)方法内部类
把类放在方法内
class Outer {
public void doSomething(){
class Inner{
public void seeOuter(){
}
}
}
}
①方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
②方法内部类对象不能使用该内部类所在方法的非final局部变量。
因为方法的局部变量位于栈上,只存在于该方法的生命期内。当一个方法结束,其栈结构被删除,局部变量成为历史。但是该方法结束之后,在方法内创建的内部类对象可能仍然存在于堆中!例如,如果对它的引用被传递到其他某些代码,并存储在一个成员变量内。正因为不能保证局部变量的存活期和方法内部类对象的一样长,所以内部类对象不能使用它们。
(5)匿名内部类
顾名思义,没有名字的内部类。表面上看起来它们似乎有名字,实际那不是它们的名字。
当程序中使用匿名内部类时,在定义匿名内部类的地方往往直接创建该类的一个对象。匿名内部类的声明格式如下:
new ParentName(){
...// 内部类的定义
}
匿名内部类就是没有名字的内部类。什么情况下需要使用匿名内部类?如果满足下面的一些条件,使用匿名内部类是比较合适的:
·只用到类的一个实例 。
·类在定义后马上用到。
·类非常小(SUN推荐是在4行代码以下)
·给类命名并不会导致你的代码更容易被理解。
在使用匿名内部类时,要记住以下几个原则:
·匿名内部类不能有构造方法。
·匿名内部类不能定义任何静态成员、静态方法。
·匿名内部类不能是public,protected,private,static。
·只能创建匿名内部类的一个实例。
·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。666