此篇文章来自一个初学Java不久的学生,内容的用词、深度、广度甚至部分理解不够到位,再加上Markdown语法的不熟练,所以排版不够美观。但还是希望有疑问的读者能够读完全文,大家遇到问题可以一起交流。谢谢!
类:使用一个通用类来定义同一类型的对象。类是一个模板或者称为合约,用来定义对象的数据域是什么以及方法是做什么的。
对象:对象代表现实世界中可以明确标识的一个实体。例如:一个学生、一张桌子甚至是一个圆都可以看作是一个对象。并且每个对象都有自己独特的标识、状态和行为。一个对象是一个类的实例
类和对象的关系:类是对事物的一种描述,对象则为具体存在的事物 。举个例子:定义一个类用来装水,那么它的对象可以是水杯也可以是茶壶。只要能够装水的都可以通过这个类来实例化获得它的对象。
如果你还是不懂怎么意思,或许你可以看一下我的面向过程编程和面向对象编程的区别,希望对你有帮助
做为一个初学者,我表示会写这句话,但是对这句话的理解就模棱两可了。
//第一种书写方式 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()方法,分别称为修改器和访问器。依靠着修改器和访问器的特性,达到数据的安全性。