面向对象(上)
一、定义
面向对象是一张符合人类思维的变成习惯。现实生活中存在各种不同形态的事务,这些事务之间存在着各种各样的关系。在程序中使用对象来映射现实中的事务,使用对象的关系来描述事务之间的关系,这种思想就是面向对象。
提到面向对象,自然会想到面向过程,面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步步实现,使用的时候依次调用就可以了。面向对象则是把构成问题的事务按照一定规则划分为多个独立的对象,然后通过调用对象的方法来解决问题。当然,一个应用程序会包含多个对象,通过多个对象的相互配合来实现应用程序的功能,这样当应用程序功能发生变动时,只需要修改个别对象就可以了,从而使代码更容易得到维护。面向对象的特点主要可以概括为:封装性、继承性、多态性,接下来针对这三种特性进行简单介绍。
1.封装性:
封装性是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体的实现细节,这就是封装思想。
2.继承性:
继承性主要描述的是类与类之间的关系,通过继承,可以在无需重新编写原有类的情况下,对原有的功能发个进行扩展。
3.多态性:
多态性指的是在程序中允许出现重名现象,它指在一个类中定义的属性和方法被其他类继承后,他们可以具有不同的数据类型或表现出不同的行为,这使得同一个属性和方法在 不同的类中具有不同的意义。
二、类和对象
面向对象的编程思想,力图让程序中对事物的描述与钙食物在现实中的形态保持一致。为了做到这一点,面向对象的思想中提出了两个概念,即类和对象。其中,类是对某一类事务的抽象描述,而对象用于表示显示中该类事务的个体。
1.类的定义
在面向对象的思想中最核心的就是对象,为了在程序中创建对象,首先需要定义一个类。类是对象的抽象,它用于描述一组对象的共同特征和行为。类中可以定义成员变量和成员方法,其中成员变量用于描述对象的特征,也被称作属性,成员方法用于描述对象的行为,可以简称方法。
例:
class Jx{
//属性
double x,y;
//操作,成员方法,函数 返回值类型 函数名(形参)
void set(double a,double b)
{this.x=a;this.y=b;}
double getArea()
{return this.x*this.y}
void output(){
System.out.println("长"+this.x);
System.out.println("宽"+this.y);
System.out.println("面积"+this.getArea());
}
}
在java中,定义在类中的变量成为成员变量,定义在方法中的变量成为局部变量。如果在某一个方法中定义的局部变量与成员变量同名,这种情况是允许的此时方法中通过变量名访问到的是局部变量,而并非成员变量,例如下面代码:
class Person{
int age=10;
void speak(){
int age=60;
System.out.println("大家好,今年我"+age+"岁");
}
}
上面代码中,在person类的speak()方法中有一条打印语句,访问了变量age,此时访问的是局部变量age,也就是说当有另外的程序调用speak方法时,输出的值时60而不是10。
2.对象的创建与使用
应用程序想要完成具体的功能,仅有类是远远不够的,还需要根据类创建实例对象。在java程序中可以使用new关键字来创建对象,具体格式如下:类名 对象名称 = new 类名()
class Person{
int age;
void speak(){
System.out.println("大家好,今年我"+age+"岁");
}
}
Person p1 = new Person();
Person p2 = new Person();
p1.age=10;
p1.speak();>>>"大家好,今年我10岁"
p2.speak();>>>"大家好,今年我0岁"
在实例化对象时,java虚拟机会自动为成员变量进行初始化,正对不同类型的成员变化,java虚拟机会赋予笔筒的初始值。
当对象被实例化后,在程序中可以通过对象的引用变量来访问该对象的成员。需要注意的是,当没有任何变量引用这个对象时,它将成为垃圾对象,不能再被使用。
class Person{
void say(){
System.out.println("大家好");
}
}
Person p = new Person();
p.say();
p = null;
p.say();
>>>
大家好
报错!!!
3.类的设计
在java中,对象时通过类创建出来的。因此,在程序设计时,最重要的就是类的设计。
假设要在程序中描述一个银行卡信息,我们可以在里面定义name、balance三个属性分别表示姓名、余额,根据这个可以设计出打印信息的方法。
class Yhzh
{//属性,成员变量
String name;//户名
double balance;//余额
public void outpit() {
System.out.println(name+"你好,您现在卡内余额为:"+balance);
}//输出帐户信息
}
要想使用这个类就可以调用该类进行玩耍了。
4.类的封装
在设计一个类时,应该对成员变量的访问做出一些限定,不允许外界随意访问,这就需要实现类的封装。
所谓类的封装是在定义一个类时,将类中的属性私有化,及时用private关键字来修饰,私有熟悉只能在他所在类中被访问,如果外界想要访问稀有属性,需要提供一些使用public修饰的共有方法,其中包括用于获取属性的getXxx方法和设置属性的setXx方法。
class Student{
private String name;//将name属性私有化
private int age;//将age属性私有化
//下面公有的方法,用于间接访问类中的属性getXxx、setXxx方法
public String getName(){
return name;
}
public String setName(String stuName){
name = stuName;
}
public int getAge(){
return age;
}
public void setAge(int stuAge){
//下面是对传入的参数进行检查
if (stuAge<0|stuAge>150){
System.out.println("您输入的用户年龄有误");
}else:{
age = stuAge;
}
}
public void output(){
System.out.println("大家好,我叫"+name+",我今年"+age+"岁。")
}
}
在主函数内:
Student su = new Student();
//su.age;//此时是报错的,因为age为私有的属性,外部并不能访问
stu.setAge(20);
stu.setName("summer");
stu.output();
>>>
"大家好,我叫summer,我今年20岁。"
三、构造方法
1.构造方法的定义
在一个类中定义的方法如果同时满足以下三个条件,该方法成为构造方法,具体如下:
- 方法名与类名相同
- 在方法名前面没有返回值类型的声明
- 在方法中不能使用return语句返回一个值,但是可以单独写return语句来作为方法的结束。
//无参
class Person{
public Person(){
System.out.println("这是一个无参的构造方法,与普通方法不一样");
}
}
//主函数内:
Person p = new Person();//实例化person对象,此时如果运行程序,就可以在console里面看到打印出来的值
//有参
class Person{
private int age;
public Person(int a){
age = a;//为属性age进行赋值
}
public void speak(){
ystem.out.println("我今年"+age+"岁。");
}
}
//主函数内
Person p = new Person(20);//实例化Person,并且构造方法实际参数
p.speak();
>>>
我今年20岁。
在java中每个类至少有一个构造方法,如果在一个勒种没有定义构造方法,系统会自动为这个类创建一个默认的构造方法,这个默认的构造方法没有函数,在其方法体中没有任何代码,即什么也不做。但是,当类中定义了构造方法时,编译的时候就不会添加默认的构造方法,如果不定义无参数构造方法,定义了有参数构造方法,创建对象时必须传递参数。如果把public改成pricate关键字修饰构造方法,则只能在类中访问,不能被外界引用
2.构造方法的重载
与普通方法一样,构造方法也可以重载,在一个类中可以定义多个构造方法,只要每个构造方法的参数类型或个数不同即可,在创建对象时,可以通过调用不同的构造方法来为不同的属性进行赋值。
class Person{
private String name;
private int age;
//定义两个参数的构造方法
public Person(String con_name,int con_age){
name = con_name;
age = con_name;
}
//定义一个参数的构造方法
public Person(String con_name){
name = con_name
}
public void speak(){
System.out.printn("大家好,我是"+name+",今年"+age+"岁。");
}
}
//主函数内
Person p1 = new Person("summer",20);
Person p2 = new Person("july");
p1.speak();
p2.speak();
>>>
"大家好,我是summer,今年20岁。"
"大家好,我是july,今年0岁。"
四、this关键字
例如都声明为gae,但是这样做又会导致成员变量和局部变量名称冲突,在方法中将无法访问成员变量age。为了解决这个问题,java中提供了一个关键字this来指代当前对象,用于在方法中访问对象的其他成员。
//demo1
class Person(){
private String name;
public Person(String name){
name = name;
}
public void speak(){
System.out.println("大家好我叫"+name);
}
}
//主函数内
Person p = new Person("summer");
p.speak()//如果局部变量和成员变量相同,则会返回null,要解决这个问题,引入this
>>>
大家好我叫null
//demo2
class Person(){
private String name;
public Person(String name){
this.name = name;
}
public void speak(){
System.out.println("大家好我叫"+name);//这里不使用this是因为speak并没有使用name这个参数,所以不用区分局部还是成员变量。
}
}
//主函数内
Person p = new Person("summer");
p.speak();
>>>
大家好我叫summer
//demo3在构造方法中调用其他构造方法。
class Person(){
private String name;
public Person(){
this("默认名字");//这个必须是第一行代码
}
public Person(String name){
name = name;
}
public void speak(){
System.out.println("大家好我叫"+name);
}
}
//主函数内
Person p = new Person();
p.speak();
>>>
大家好我叫默认名字
五、static关键字
在定义一个类时,只是在描述某事物的特征和行为,并没有产生具体数据。只有通过new关键字创建该类的实例对象后,系统才会为每个对象分配空间,存储各自的数据。有时候开发人员会希望某些特定的数据在内存中只有一份,而且能够被一个类的所有实例对象所共享。
例:某个学校所有学生共享同一个学校名名称,此时完全不必要在每个学生对象所占的内存空间中都定义一个变量来表示学校名称,而可以在对象以外的空间定义一个表示学校名称的变量,让所有对象来共享。
在一个java类中,可以使用static关键字来修饰成员变量,该变量被称作静态变量。静态变量被所有实例共享,可以使用“类型.变量名"的形式来访问。注意:static关键字只能用于修饰成员变量,不能用于修饰局部变量,否则编译会报错
class Student{
static String schoolName;//使该变量变成静态变量
}
//主函数内
Student su1 = new Student();
Student su2 = new Student();
//静态成员的调用方式:类名.对象
Student.schoolName = "Nxist";//为静态变量赋值
System.out.println("我的学校是"+stu1.schoolName);//打印第一个学生的学校名字
System.out.println("我的学校是"+stu2.schoolName);//打印第二个学生的学校名字
静态代码块
在java类中,使用一对大括号包围起来的若干行代码被称为一个代码块,用static关键字修饰的代码块成为静态代码块。当类被加载时,静态代码块会执行,由于类只加载一次,因此静态代码块只执行一次。在程序中,通常会使用静态代码块来对类的成员变量进行初始化。
calss Person{
static{//静态代码块
System.out.println("Person中的静态代码块");
}
}
//主函数内
Person p1 = new Person();
Person p2 = new Person();
>>>//只打印一次
"Person中的静态代码块"
六、内部成员类
在java中,允许一个类的内部定义类,这样的类称作内部块,这个内部类所在的类成作外部块。根据内部类的位置、修饰符和定义的方式可以分为:成员内部类、静态内部类、方法内部类。
在一个类中除了可以定义成员变量、成员方法,还可以定义类,这样的类被称作成员内部类。在成员内部类中,可以访问外部类的所有成员。
如果想通过外部类去访问内部类,则需要通过外部类对象去创建内部类对象,创建内部类对象的具体格式如下:外部类.内部类型 变量名 = new 外部类名().new 内部类名();
//demo1
class Outer{
private int num = 4;
//定义一个成员方法,访问内部类
public void text(){
Inner inner = new Inner();
inner.show();
}
//定义一个成员内部类
class Inner{
public void show(){
//在成员内部类的方法中去访问外部类的成员变量是可以的
System.out.println("num="+num);
}
}
}
//主函数内
Outer outer = new Outer();
outer.text();
>>>
num=4
//demo2
class Outer{
private int num = 4;
//定义一个成员内部类
class Inner{
public void show(){
//在成员内部类的方法中去访问外部类的成员变量是可以的
System.out.println("num="+num);
}
}
}
//主函数内
Outer.Inner inner = new Outer().new Inner();
inner.show();
>>>
num=4