第三 章面向对象 第一步部分
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第三 章面向对象 第一步部分相关的知识,希望对你有一定的参考价值。
一、类与对象的基本概念
类:抽象的概念集合,表示的是一个共性的产物,类之中定义的是属性和行为(方法);
对象:是一种个性的表示,表示一个独立的个体,每个对象拥有自己独立的属性,依靠属性区分不同的对象。
类与对象的区别:类是对象的模板,对象是类的实例,类只有通过对象才可以使用,开发中应该先产生类,再产生对象。类不能直接使用,方法可以直接使用。
二、类与对象的定义
1、类的定义:
在JAVA中定义类,可以使用class关键字完成, 语法为:
1 class 类名称{ 2 属性(变量); 3 行为(方法); 4 }
范例:定义一个Person类。
1 class Person { 2 String name; 3 int age; 4 5 public void tell() { 6 System.out.println("姓名:" + name + ",年龄:" + age); 7 } 8 }
2、对象的定义:
定义完类之后,无法直接使用,要使用,必须依靠对象使用,由于类属于引用数据,对象的定义格式如下:
格式一:声明并实例化对象
类名称 对象名称 = new 类名称 ()
格式二:分布完成
声明对象: 类名称 对象名称 = null;
实例化对象: 对象名称 = new 类名称();
以后只要是引用数据类型的实例化操作,永远都会存在关键字new(分配空间)。当一个实例化的对象产生后,可以按照如下方式进行类的操作:
- 方法.属性:表示调用类之中的属性
- 方法.对象():表示调用类之中的方法
范例1:使用对象操作类
1 class Person1 { 2 String name; 3 int age; 4 5 public void tell() { 6 System.out.println("姓名:" + name + ",年龄:" + age); 7 } 8 } 9 10 public class TestPerson { 11 public static void main(String[] args) { 12 Person1 per = new Person1(); 13 per.name = "张三"; 14 per.age = -30; 15 per.tell(); 16 } 17 }
姓名:张三,年龄:-30
格式二分步完成操作类,范例2
1 class Person1 { 2 String name; 3 int age; 4 5 public void tell() { 6 System.out.println("姓名:" + name + ",年龄:" + age); 7 } 8 } 9 10 public class TestPerson { 11 public static void main(String[] args) { 12 Person1 per = null; 13 per = new Person1(); 14 per.name = "张三"; 15 per.age = -30; 16 per.tell(); 17 } 18 }
姓名:张三,年龄:-30
格式一与格式二运行结果一致,两者的区别引入内存解释:
堆内存:保存真正的数据
栈内存:保存一块堆内存的空间地址
上图为上述程序的内存分析图,过程:声明对象——实例化对象——为对象的name属性赋值——为对象的age属性赋值
范例3、产生两个对象的操作:
1 class Person1 { 2 String name; 3 int age; 4 5 public void tell() { 6 System.out.println("姓名:" + name + ",年龄:" + age); 7 } 8 } 9 10 public class TestPerson { 11 public static void main(String[] args) { 12 Person1 per2 = new Person1(); 13 Person1 per1 = null; 14 per1 = new Person1(); 15 16 per1.name = "张三"; 17 per2.name = "李四"; 18 per1.age = 30; 19 per2.age = 20; 20 per1.tell(); 21 per2.tell(); 22 } 23 }
姓名:张三,年龄:30
姓名:李四,年龄:20
内存分析图:声明per1,声明并实例化per2——实例化per2——为per1对象属性赋值——为per2对象属性赋值
范例4、异常代码:
1 class Person1 { 2 String name; 3 int age; 4 5 public void tell() { 6 System.out.println("姓名:" + name + ",年龄:" + age); 7 } 8 } 9 10 public class TestPerson { 11 public static void main(String[] args) { 12 Person1 per1 = null;//只声明,未实例化per1,只有栈内存,没有堆内存 13 per1.name = "张三"; 14 per1.age = 30; 15 per1.tell(); 16 17 } 18 }
运行结果:Exception in thread "main" java.lang.NullPointerException(空间指向异常)
at hello.TestPerson.main(TestPerson.java:15)
这种异常只会在在用数据类型产生,并很常见,解决方案:查找引用数据类型,观察其是否被实例化
引用传递:同一块堆内存空间同时被多个栈内存所指向,不同的栈可以修改同一块堆内存的内容。
范例4:
1 class Person1 { 2 String name; 3 int age; 4 5 public void tell() { 6
System.out.println("姓名:" + name + ",年龄:" + age); 7 } 8 } 9 10 public class TestPerson { 11 public static void main(String[] args) { 12 Person1 per1 = new Person1(); 13 per1.name = "张三"; 14 per1.age = 20; 15 Person1 per2 = per1; 16 per2.name = "李四"; 17 per1.tell(); 18 19 } 20 }
姓名:李四,年龄:20
范例5:
1 class Person1 { 2 String name; 3 int age; 4 5 public void tell() { 6 System.out.println("姓名:" + name + ",年龄:" + age); 7 } 8 } 9 10 public class TestPerson { 11 public static void main(String[] args) { 12 Person1 per1 = new Person1(); 13 Person1 per2 = new Person1(); 14 per1.name = "张三"; 15 per1.age = 20; 16 per2.name = "李四"; 17 per2.age = 30; 18 per2 = per1; 19 per2.name = "王五"; 20 per1.tell(); 21 22 } 23 }
结果:姓名:王五,年龄:20
垃圾:在开发程序中,没有任何对象所指向的一块堆内存空间,这块内存空间被称为垃圾,所有垃圾等待GC(垃圾收集器)不定期的进行回收与空间的释放。
3、封装性
范例1:
1 public class Person1 { 2 String name; 3 int age; 4 5 public void tell() { 6 System.out.println("姓名:" + name + ",年龄:" + age); 7 } 8 }
1 public class TestDemo2{ 2 public static void main(String[] args) { 3 Person1 p = new Person1(); 4 p.name="王娜"; 5 p.age=-30; 6 p.tell(); 7 } 8 }
运行结果:姓名:王娜,年龄:-30
虽然年龄不可能为负数,但是依然可以执行,这属于业务逻辑错误,出错的关键是没有检查要设置的内容,检查的第一步是让用户看不见操作的东西,此时,用private关键字,将类中的属性进行私有化操作。
范例2:使用private封装类中属性
1 class Person4 { 2 private String name; 3 private int age; 4 5 public void tell() { 6 System.out.println("姓名:" + name + ",年龄:" + age); 7 } 8 9 } 10 11 public class Person3 { 12 public static void main(String[] args) { 13 Person4 per = new Person4(); 14 per.name = "张三";//语法错误,无法访问私有属性 15 per.age = -30;//语法错误,无法访问私有属性 16 per.tell();//对象.方法 17 } 18 }
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The field Person4.name is not visible
The field Person4.age is not visible
at hello.Person3.main(Person3.java:16) 属性被封装,但是无法被外部操作,为此,如果访问类中的私有属性,按如下形式定义操作方法:
setter(以"private String name"属性为例):public void setName(String n);
getter(以"private String name"属性为例):public void getName().
范例3:编写setter()和getter()方法
1 public class Person { 2 private String name; 3 private int age; 4 5 public void setName(String n) { 6 name = n; 7 } 8 9 public void setAge(int a) { 10 age = a; 11 } 12 13 public String getName() { 14 return name; 15 } 16 17 public int getAge() { 18 return age; 19 } 20 21 public void tell() { 22 System.out.println("姓名:" + name + ",年龄:" + age); 23 } 24 }
1 public class Person1 { 2 public static void main(String[] args) { 3 Person per=new Person(); 4 per.setName("张三"); 5 per.setAge(20); 6 per.tell(); 7 } 8 }
姓名:张三,年龄:20
虽然以上代码可以访问,但是没有加入验证。在开发时,加入验证是在setter中加入,getter只是简单的将数据返回。
范例4:加入验证
1 public class Person { 2 private String name; 3 private int age; 4 5 public void tell() { 6 System.out.println("姓名:" + name + ",年龄:" + age); 7 } 8 public void setName(String n){ 9 name=n; 10 } 11 public void setAge(int a){ 12 if(a>=0&&a<=0){ 13 age=a; 14 } 15 } 16 public String setName(){ 17 return name; 18 } 19 public int setAge(){ 20 return age; 21 } 22 }
1 public class Person1 { 2 public static void main(String[] args) { 3 Person per=new Person(); 4 per.setName("张三"); 5 per.setAge(-20); 6 per.tell(); 7 } 8 }
姓名:张三,年龄:0
年龄是-20,不符合逻辑,故置0.
以后在定义类的时候,所有属性都要编写private封装,封装后的属性如果需要被外部操作,则编写setter()和getter()。
4、构造方法(构造方法是在实例化对象的时候使用,而普通方法是在实例化对象产生之后使用的)
定义:构造方法的名称和类名称保持一致;
构造方法不允许有返回值声明;
由于对象实例化操作一定需要构造方法的存在,所以,如果在类中没有明确定义构造方法的话,则会自动生成一个无参,无返回值的构造方法,如果一个类之中已经明确定义了一个构造方法的话,则无实际意义的构造方法就不会自动生成,即一个类之中至少存在一个构造方法。
范例4.1:默认情况下会存在一个无参无返回值的构造方法。
1 class Person(){//类名称首字母大写 2 public Person(){//无参无返回值的方法 3 } 4 }
作用:在对象实例化的时候,通过构造方法为类中的属性初始化。
范例4.2:在类中定义有参构造方法。
1 public class Person { //类名称首字母大写 2 private String name; //属性封装 3 private int age; //属性封装 4 5 public Person(String n, int a) { //通过构造方法赋值 6 setName(n); //设置name属性内容 7 setAge(a); //设置age属性内容 8 } 9 10 public void tell() { 11 System.out.println("姓名:" + name + ",年龄:" + age); 12 } 13 14 public void setName(String n) { //setter:设置name属性内容 15 name = n; 16 } 17 18 public void setAge(int a) { //setter:设置age属性内容 19 if (a >= 0 && a <= 250) { //增加检查 20 age = a; //满足条件赋值 21 } 22 } 23 24 public String getName() { //getter:取得name属性 25 return name; 26 } 27 28 public int getAge() { //getter:取得age属性 29 return age; 30 } 31 }
1 public class TestDem { 2 public static void main(String[] args) { 3 Person per = new Person("张三", 30);// 声明并实例化对象 4 per.tell();// 对象.方法() 5 } 6 }
姓名:张三,年龄:30
另外:可以用”this.()方法“表示调用本类中的方法,以下代码与范例4.2中代码一样
1 public Person(String n, int a) { //通过构造方法赋值 2 this.setName(n); //设置name属性内容 3 this.setAge(a); //设置age属性内容 4 }
范例4.3:构造方法重载
1 public class Person { // 类名称首字母大写 2 private String name; // 属性封装 3 private int age; // 属性封装 4 5 public Person() { // 无参构造方法 6 } 7 8 public Person(String name) { 9 this.setName(name); 10 } 11 12 public Person(String n, int a) { 13 setName(n); 14 setAge(a); 15 } 16 17 public void tell() { 18 System.out.println("姓名:" + name + ",年龄" + age); 19 } 20 21 public void setName(String n) { 22 name = n; 23 } 24 25 public void setAge(int a) { 26 if (a >= 0 && a <= 250) { 27 age = a; 28 } 29 } 30 31 public String getName() { 32 return name; 33 } 34 35 public int getAge() { 36 return age; 37 } 38 }
public class TestDem { public static void main(String[] args) { Person per = new Person("张三");// 声明并实例化对象 per.tell();// 对象.方法() } }
姓名:张三,年龄0
在本程序Person类中定义了三个构造方法,在主类中实例化对象时调用了一个参数的构造,结果只为name赋值,年龄为0.
在一个类中对构造方法重载时,所有的重载方法按照参数的个数由多到少或由少到多
5、匿名对象
按内存关系,对象名称可以被解释为在栈内存中保存,而对象的具体内容(属性)在对内存之中保存,所以匿名对象没有对应的栈内存指向,只能使用一次,一次之后将成为垃圾,并且等待GC回收释放。
范例:
1 public class Person { 2 private String name; 3 private int age; 4 5 public Person(String n, int a) { 6 name = n; 7 age = a; 8 } 9 10 public void tell() { 11 System.out.println("姓名:" + name + ",年龄" + age); 12 } 13 // settter、getter省略 14 }
1 public class TestDem { 2 public static void main(String[] args) { 3 new Person("张三", 20).tell();// 匿名对象.方法 4 } 5 }
姓名:张三,年龄20
以上是关于第三 章面向对象 第一步部分的主要内容,如果未能解决你的问题,请参考以下文章