《Java从入门到精通》第七章学习笔记

第7章 类和对象

一、类和对象的定义及关系

1、类是同一类别对象的抽象定义;可以理解为是某一类具体对象的模子,确定对象将会拥有的特性,包括该类对象具备的属性和方法。

2、对象是对类的一种具体化的客观存在,是对类的具体实例化。要创建一个对象,必须基于类,即先要创建可描述该对象的类。

3、创建一个类

 1 public class Telphone {
 2     //属性(成员变量):有什么
 3     float screen;
 4     float cpu;
 5     float mem;
 6     //方法 :干什么
 7     void call(){
 8         System.out.println("Telphone有打电话的功能!");
 9     }
10     void sendMessage(){
11         System.out.println("Telphone有发短信的功能!");
12     }
13 }

4、创建一个对象
针对上面代码创建类的创建对象方法

Telphone myphone=new Telphone();

5、对象的比较:

有两种方法,分别为“==”运算符和equals()方法,但两者有本质的区别:
(1)“==”运算符比较的是两个对象引用的地址是否相同;
(2)equals()方法比较的是两个对象引用所指的内容是否相同。

 1 public class ClassCompare {
 2     public static void main(String[] args) {
 3         String c1=new String("abc");
 4         String c2=new String("abc");
 5         String c3=c1;
 6         System.out.println("c2==c3的运算结果为: "+(c2==c3));
 7         System.out.println("c2.equals(c3)的运算结果为: "+(c2.equals(c3)));
 8     }
 9 }
10 /*首先为c1分配一块内存区域存储字符串abc,并将c1指向设为该内存区域
11  *然后同样为c2分配另外一块内存区域存储字符串abc,并将c2指向设为该内存区域
12  *最后把c3的引用指向c1的指向
13 */

6、类的使用
同样针对上面创建的Telphone类:

 1 public class InitialTelphone {
 2     public static void main(String[] args) {
 3         // TODO Auto-generated method stub
 4         Telphone phone=new Telphone();
 5         phone.sendMessage();
 6         //这里各实例属性值在未初始化赋值的时候默认为0
 7         phone.screen=5.0f;
 8         phone.cpu=1.4f;
 9         phone.mem=2.0f;
10         phone.sendMessage();
11         //赋值后的显示
12     }
13 }

二、成员变量和局部变量
1、成员变量:在类中定义,用于描述对象的属性;成员变量可以被本类的方法使用,也可以被其他类的方法使用(依据该成员变量定义时的修饰词)。
2、局部变量:在类的方法中定义,在方法中临时保存数据。局部变量只能在当前方法中使用。
3、区别:局部变量的作用域仅限于定义的方法内部;成员变量的作用域在整个类内部都是可见的。Java中会给成员变量赋初始值,但不会给局部变量默认赋初值,所以局部变量在使用前必须要赋值,否则会报错。
4、同一个方法中不能用同名的局部变量;在不同的方法中,可以有同名局部变量。如果局部变量和成员变量同名,在定义该局部变量的方法内部局部变量有更高的优先级。

 1 public class Telphone {
 2     float screen;
 3     float cpu;
 4     float mem;
 5     int var;
 6     void call(){
 7         int localVar=10;
 8         System.out.println(var);
 9         //可以调用类的成员变量var,默认值为0
10         System.out.println("Telphone有打电话的功能!");
11     }
12     void sendMessage(){
13         System.out.println(localVar);
14         //调用call()方法中的局部变量会报错
15         System.out.println("Telphone有发短信的功能!");
16     }
17 }

三、类的构造方法
1、构造方法是定义在Java类中的一个用来初始化对象的方法。构造方法与类同名,并且没有返回值。
2、如果类定义中没有设置无参数的构造方法,则系统会自动生成。

 1 //设置无参数的构造方法
 2 public class Telphone {
 3     int sc=10;  //定义成员变量
 4     public Telphone(){
 5         System.out.println("无参的构造方法执行了");
 6     }
 7 }
 8 public class InitialTelphone {
 9     public static void main(String[] args) {
10         Telphone phone=new Telphone();
11         //可以看到构造方法执行了
12         System.out.println(phone.sc);
13         //可以看到输出了成员变量sc的值为10
14         //当没有设置无参构造方法时,默认的无参构造方法会使对象拥有成员变量这个实例属性
15         //当定义了无参构造方法时,即便没有显式的定义成员变量的赋值,对象也会拥有成员变量对应的实例属性
16     }
17 }

3、有参数的构造方法通常只有一个目的:即给成员变量赋初值。

 1 public class Telphone {
 2     float screen;
 3     float cpu;
 4     float mem;
 5     public Telphone(){
 6         System.out.println("无参的构造方法执行了");
 7     }
 8     //有参构造方法与无参构造方法同名
 9     public Telphone(float screen,float cpu,float mem){
10         screen=screen;
11         cpu=cpu;
12         mem=mem;
13         System.out.println("有参的构造方法执行了");
14     }
15 }
16 public class InitialTelphone {
17     public static void main(String[] args) {
18         // TODO Auto-generated method stub
19         Telphone phone=new Telphone();
20         Telphone phone1=new Telphone(5.2f,1.4f,2.0f);
21     }
22 }

4、当类中定义了构造方法(不管是有参还是无参)时,系统都不会再默认生成无参的构造方法。
5、构造方法的重载:方法名相同,但参数不同的多个构造方法,调用时候会自动判断、根据不同的参数组合选择对应的构造方法。如上面代码中无参和有参的构造方法为同名,都可以使用。
6、构造方法中一般可以添加保证赋值合理的功能。

 1 public class Telphone {
 2     float screen;
 3     float cpu;
 4     float mem;
 5     public Telphone(){
 6         System.out.println("无参的构造方法执行了");
 7     }
 8     public Telphone(float screen,float cpu,float mem){
 9         if(screen<3.5){
10             System.out.println("赋值不合理,已自动赋值screen为3.5");
11             screen=3.5f;
12         }else{
13             screen=screen;
14         }
15         cpu=cpu;
16         mem=mem;
17         System.out.println("有参的构造方法执行了");
18     }
19 }

四、静态变量和静态方法
1、静态变量:当同一个类的两个或者多个对象需要在同一个内存区域共享一个数据时,可以通过定义类的静态变量来实现。由static修饰的成员变量即是静态变量。静态变量可以通过类名.静态变量名,也可以通过实例对象名.静态变量名来访问,但因为是同一类所有实例对象的共享,所以一般采用类名.静态变量名的方式进行访问。
2、静态方法:对于方法的静态修饰,与上述静态变量规则一致。需要注意:
(1)静态方法可以直接调用同一个类中的静态成员(包括静态变量和静态方法),但不能直接调用非静态成员。如果要调用一个类中的非静态成员,则必须先实例化对象,通过实例对项目名.非静态成员来调用。
(2)与静态成员方法不一样的是在普通成员方法中可以直接访问同类的非静态和静态变量。

public class HelloWorld {
    String name="imook";
    static String hobby="java";
    public void show(){
        System.out.println(name);  //普通成员方法中可以使用非静态成员
        System.out.println(hobby); //也可以使用静态成员
    }

    public static void main(String[] args) {
        System.out.println(name);  //错误!静态方法main中不能使用类中的非静态成员
        System.out.println(HelloWolrd.name);  //错误同上
        System.out.println(hobby);  
        //静态方法中可以直接调用静态成员
        System.out.println(HelloWorld.hobby); 
        //也可以通过类名.静态成员名进行调用
        HelloWorld myHelloWorld=new HelloWorld();  
        //创建一个实例对象
        System.out.println(myHelloWorld.name);
        //可以通过实例对象名.非静态成员名进行调用
        System.out.println(myHelloWorld.hobby);
        //也可以通过实例对象名.静态成员名进行调用(但不推荐)
        HelloWorld.show(); //错误!静态方法main中不能使用类中的非静态成员
        show();         //错误同上!
        myHelloWorld.show();
    }
}

3、通过static静态初始化块:静态初始化块只在类加载时执行,且只执行一次,并且静态初始化块只能给静态变量赋值,不能给普通成员变量赋值。

 1 public class HelloWorld {
 2     int num1;
 3     int num2;
 4     static int num3;
 5 
 6     public HelloWorld(){
 7         num1=11;
 8         System.out.println("通过构造方法给num1赋初值!");
 9     }
10     {//通过普通初始化块给num2赋初值
11         num2=222;
12         System.out.println("通过构造方法给num2赋初值!");
13     }
14     static{ //通过静态初始化块给静态变量num3赋初值
15         num3=3333;
16         System.out.println("通过构造方法给num3赋初值!");
17     }
18 
19     public static void main(String[] args) {
20         HelloWorld hello=new HelloWorld();  //构造方法创建类的实例对象hello
21 /*
22  * 本次使用构造方法时,程序第一次加载HelloWorld类,会先执行静态初始化块,对应给num3赋值3333,并输出"通过构造方法给num3赋初值!"
23  * 再执行普通初始化块,对应给num2赋值222并输出"通过构造方法给num2赋初值!"
24  * 最后才执行构造方法,对应给num1赋值11并输出"通过构造方法给num1赋初值!"
25  */
26         System.out.println("hello的num1:"+hello.num1); //普通成员通过实例对象名访问
27         System.out.println("hello的num2:"+hello.num2);
28         System.out.println("hello的num3:"+num3);  //静态成员直接访问
29         HelloWorld hello2=new HelloWorld();  //构造方法创建类的实例对象hello2
30 /*因静态初始化块只在加载时执行一次,所以这次创建对象时不执行静态初始化块
31  * 这里不执行也是可以理解的,因为构造方法本身不包括静态初始化块,自然不会执行
32  * 前次创建hello对象时并不是因为构造方法而去执行静态初始化块,而是加载类的时候执行
33  */
34     }
35 }

五、访问修饰符和this关键字
1、访问修饰符包括privateprotectedpublic;其中private范围对应为本类;protected范围对应本类、子类和同包;public范围为本类、子类、同包及其他包。如果没有使用访问修饰符,则默认的访问范围是本类和同包。
2、this关键字用于引用对象,实质上是对一个对象的引用。有些情况下可以省略this 关键字,如下例代码:

private void setName(String name){
    this.name=name; //这里可以省略this,写成name=name;
}

在当需要返回一个类的对象时则必须显式的使用this关键字:

/*创建一个返回类型为Book类的方法
 *方法名为getBook
 */使用this引用对象将Book类的对象返回
public Book getBook(){    
    return this;
}

六、实例

 1 //汉诺塔
 2 public class HanoiTower {
 3     public static int moveTimes=0;//设置全类下的静态变量,计步器
 4     public static void moveDish(int num,char a,char b,char c){
 5         if(num==1){
 6             System.out.println("Move dish from "+a+" to "+c);
 7             moveTimes++;
 8         }else{
 9             moveDish(num-1,a,c,b);
10             //先把num-1个盘子从a通过c放到b;这里不涉及具体的移动,而是调用方法,所以计步器不加
11             System.out.println("Move dish from "+a+" to "+c);
12             //然后再把a上剩余的最后一个移动到c,这里涉及到具体的移动步骤,所以计步器加1
13             moveTimes++;
14             moveDish(num-1,b,a,c);
15             //最后解决b上的num-1个盘子,通过a再移动到c
16         }
17     }
18 
19     public static void main(String[] args) {
20         // TODO Auto-generated method stub
21         int numTimes=12;
22         moveDish(numTimes,'A','B','C');
23         System.out.println("总共移动了"+moveTimes+"次!");
24     }
25 }
原文地址:https://www.cnblogs.com/tsembrace/p/4574579.html