一、引言
此篇文章来自一个初学Java不久的学生,内容的用词、深度、广度甚至部分理解不够到位,再加上Markdown语法的不熟练,所以排版不够美观。但还是希望有疑问的读者能够读完全文,大家遇到问题可以一起交流。谢谢!
二、类和对象的初步理解
类:使用一个通用类来定义同一类型的对象。类是一个模板或者称为合约,用来定义对象的数据域是什么以及方法是做什么的。
对象:对象代表现实世界中可以明确标识的一个实体。例如:一个学生、一张桌子甚至是一个圆都可以看作是一个对象。并且每个对象都有自己独特的标识、状态和行为。一个对象是一个类的实例
类和对象的关系:类是对事物的一种描述,对象则为具体存在的事物 。举个例子:定义一个类用来装水,那么它的对象可以是水杯也可以是茶壶。只要能够装水的都可以通过这个类来实例化获得它的对象。
如果你还是不懂怎么意思,或许你可以看一下我的面向过程编程和面向对象编程的区别,希望对你有帮助
三、五个有必要知道问题
一、正确理解A a = new A();
做为一个初学者,我表示会写这句话,但是对这句话的理解就模棱两可了。
//第一种书写方式
A a;
a = new A ();
//第二种书写方式
A a = new A ();
第一种书写方式:
第一步:声明一个A类型的变量a
第二步:创建一个A类型的对象,并且将它赋值给变量a
第二种书写方式:
声明一个A的变量a,用来引用变量,再创建一个对象,并且将创建的对象赋值给变量a。
总结的大白话:看到new就是需要在堆内存里面开辟一块属于类A的空间,然后把开辟出来的空间的地址值赋值给a,当然这个a一定要是这个类型的变量,当然如果你学了多态,这里可能又要进行讨论一番。
注意:从表面上看,对象引用变量中似乎存放了一个对象,但事实上,它只是包含了对该对象的引用。严格的来说,对象引用变量和对象是不同的,但是大多数情况下,这种差异是可以忽略的。因此可以简单的说a是A的一个对象,而不用花大篇幅的来说,a是一个包含对A对象引用的变量。简单的理解就是:a是抽象出来的一个地址值,它可以不用一个实体(因为它只是把这个地址值当作了一个实体),但是它依然可以完成a对A里面方法的操作(借助地址值)。
二、基本类型变量与引用类型变量的区别
每一个变量都代表一个存储值得内存位置。声明一个变量时,就是在告诉编译器这个变量可以存放什么类型得值。对基本数据类型变量来说,对应内存所存储得值时基本类型值。对引用类型变量来说,对应内存所存储得值时一个引用,是对象得存储地址。换句话说,你得变量是在堆内存还是在栈内存,如果是堆内存就是引用类型变量,如果是栈内存,那就是基本类型变量。
三、局部变量和成员变量的区别
1.类中位置不同:成员变量(类中方法外)局部变量(方法内部或方法声明上)
2.内存中位置不同:成员变量(堆内存)局部变量(栈内存)
3.生命周期不同:成员变量(随着对象的存在而存在,随着对象的消失而消失)局部变
量(随着方法的调用而存在,随着方法的调用完毕而消失)
4.初始化值不同:成员变量(有默认初始化值)局部变量(没有默认初始化值,必须先
定义,赋值才能使用)
四、静态和实例的区别
我这里只说着重说方法的区别
其实我在很早学习方法的时候就意识到这个问题了,为什么有的方法是需要实例化以后,依靠对象来调用方法;但是有的又是可以直接.出来(Math类)。其实这就是两个类的本质的区别。
静态方法:直接用.的方式直接调用方法
实例化方法:需要创建这个类的对象,然后通过对象调用类里面的方法
再来一个例子:
总结:其实在最后的那个例子里面不难看出,其实静态的方法也可以通过实例化的方式调用,但是通过实例化的方法调用,会在堆里面开辟一块内存空间,加重系统负担,静态的调用消耗的内存是在方法区。而且实例化的方法却不能通过静态的方式调用。
静态变量:其实主要的核心思想静态变量和静态方法差不多,补充一点就是,静态变量的值会随着全局的变动而变动。即你调用了一次并且赋值了,那么它就一直会跟着变。
五、构造方法
我习惯把构造方法当做一个类得灵魂。一个类是肯定需要一个灵魂。无参构造方法就是最初得灵魂,你自己写了一个带参得构造方法,那么就相当于你给这个类赋予了一个新得灵魂。
格式:
public class People1 {
int age;
String name;
//无参构造方法
public People1() { }
//带参构造方法
public People1(int age, String name) {
this.age = age;
this.name = name;
}
}
之前在继承的那篇文章里面说过,如果对继承不理解的小伙伴,可以去看看面向对象三大特性之——继承。当然里面是侧重说重写于重载得区别,其实带参构造方法和无参构造方法就是重载。
为什么需要构造方法呢?
答:每一个类在创建的时候我们一定要赋予它灵魂,请记住这句话。当然,在你每次new一个类的时候,它也就会自动运行构造方法。为什么之前你new了那么多类,没有注意到这个?因为你之前的灵魂都是与生俱来的(默认无参构造)。我想如果你需要它的带参构造方法,你可能就一目了然了。
四、封装核心
需求:定义一个People类用于打印输出人的姓名和年龄
一、没有运用封装技术的代码
People类:
public class People {
//定义的成员属性
int age;
String name;
//定义的show方法
public void show() {
System.out.println("输出的人的名字是:" + name + "年龄是:" + age);
}
}
测试类:
public class Demo {
public static void main(String[] args) {
People p = new People();
p.age= 4;
p.name = "小明";
p.show();
}
}
输出结果:
输出的人的名字是:小明年龄是:4
二、运用封装技术以后的代码
People类:
public class People1 {
private int age;
private String name;
//两个构造方法
public People1() { }
public People1(int age, String name) {
this.age = age;
this.name = name;
}
//对age成员变量的封装
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//对name成员变量的封装
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//定义的show方法
public void show() {
System.out.println("输出的人的名字是:" + name + "年龄是:" + age);
}
}
测试类:
public class Demo1 {
public static void main(String[] args) {
People1 p = new People1();
p.setAge(4);
p.setName("小明");
p.show();
}
}
输出结果:
输出的人的名字是:小明年龄是:4
三、两种的区别
其实我最开始学习这种封装写法的时候很不习惯,因为我觉得效果是一样的,为什么还要这么复杂?慢慢的,发现里面并不是这么简单。不然我问你几个问题?
1)如果封装类型的代码块里面,没有setXxx()方法,会怎么样?
答:如果没有setXxx()那么对于该方法下的数据将缺少一个设置程序,那么在给数据域里面的数据进行设置数据的时候将会报错。当然,如果你不去设置,那么就不会报错,因为这是引用数据类型,你不赋值将会被默认值取代。
2)在setXxx()方法里面加入部分条件语句,会怎么样?
答:这里就体现了封装的数据安全,对于用户输入的数据需要保证其正确性,但是用户的输入误差太大,这个时候就需要代码的提示。
3)private关键字去掉会怎么样?
答:去掉private关键字后,将会失去数据的封装性,那个在外界就可以直接利用对象.成员变量的方法修改数据。这样就会失去setXxx()/getXXxx()方法本来的意义。
四、总结
使用封装的技术主要是为数据的安全而提供的一种使用方式,将数据域设置为私有的保护数据,使程序更安全而更有利于后期的维护。出于不能让外界的数据直接访问内部数据,所以使用了关键字private,但是有的时候,我们又需要对数据域中的数据进行操作,所以我们就需要提供一组setXxx()/getXXxx()方法,分别称为修改器和访问器。依靠着修改器和访问器的特性,达到数据的安全性。
标签:封装,name,构造方法,对象,age,面向对象,public,三大,变量 From: https://blog.51cto.com/u_15942107/6017186