Java面向对象笔记 • 【第2章 面向对象进阶】

全部章节   >>>>


本章目录

2.1 成员变量

2.1.1 成员变量与局部变量的区别

2.1.2 成员变量的使用

2.1.3 实践练习

2.2 this关键字

2.2.1 使用this关键字引用成员变量和成员方法

2.2.2 解决实例变量与局部变量同名的问题

2.2.3 实践练习

2.3 隐藏和封装

2.3.1 封装

2.3.2 Java访问控制符

2.3.3 实践练习

2.4 static关键字

2.4.1 静态成员变量

2.4.2 静态方法

2.4.3 静态代码块

2.4.4 实践练习

总结:


2.1 成员变量

类体中定义的变量为成员变量,作用范围是整个类,只要在这个类中都可以访问到它。

成员变量包括实例属性了类属性。

类属性从类被加载开始存在,直到系统完全销毁该类,类属性的作用域与该类的生命周期相同

实例属性则从类的实例被创建起开始存在,直到系统销毁该实例,实例属性的作用域与其对应的实例的生命周期相同

2.1.1 成员变量与局部变量的区别

类中的位置不同:

成员变量:在类中方法外面。

局部变量:在方法或者代码块中,或者方法的声明上(即在参数列表中)。

内存中的位置不同:

成员变量在堆中(方法区中的静态区)。

局部变量:在栈中。

生命周期不同:

成员变量随着对象的创建而存在,随着对象的消失而消失。

局部变量随着方法的调用或者代码块的执行而存在,随着方法的调用完毕或者代码块的执行完毕而消失。

初始值:

成员变量有默认初始值。

局部变量:没有默认初始值,使用之前需要赋值,否则编译器会报错。

2.1.2 成员变量的使用

示例:测试英雄对象中成员属性的赋值和引用

public class Hero {	
	String name;//英雄名字
	int  age;//英雄年龄

	public static void main(String[] args){
		//创建英雄对象hero1
		Hero hero1 = new Hero();
		hero1.name="德鲁伊";  //为hero1的实例属性name赋值
		hero1.age=45;					
		//创建英雄对象hero2
		Hero hero2 = new Hero();
		System.out.println("英雄hero1的名字:"+hero1.name
			+"\t"+"年龄:"+hero1.age);
		System.out.println("英雄hero2的名字:"+hero2.name
			+"\t"+"年龄:"+hero2.age);	
	}
}

实例属性内存分配示意图

2.1.3 实践练习

2.2 this关键字

1、this关键字代表自身

2、this关键字主要用途

  • this代表自身类的对象(直接使用this使用this引用成员变量、使用this调用成员方法)。
  • this在自身的构造方法内部调用其他的构造方法。

2.2.1 使用this关键字引用成员变量和成员方法

示例:测试在方法中使用this关键字引用成员变量和成员方法

public class Hero {
	public void jump(){
		System.out.println("---英雄遇到了障碍需要跳过去---");
	}
	public void run(){
		System.out.println("---执行run方法英雄正在奔跑---");
        		Hero hero = new Hero();//创建Hero对象
        		System.out.println("her对象已经被创建内存地址
        			为:"+hero.hashCode()+",它将实行jump方法");
		hero.jump();//调用run()方法
	}
}
public class TestHero {
   	public static void main(String[] args){
		Hero hero = new Hero();//创建Hero对象
		System.out.println("hero对象已经被创建内存地址
       			为:"+hero.hashCode()+",它将实行run方法");
		hero.run();//调用run()方法
	}
}

2.2.2 解决实例变量与局部变量同名的问题

示例:实例变量与句变量同名(实例变量前没有this

public class Hero {
	 String name;

	 public void setName(String name){
		 name=name; //此处易混淆,可读性差
	 }
	 public  static void main(String[] args){
		 Hero hero=new Hero();
		 hero.setName("风暴精灵");
		 System.out.println("hero的名字为:"+hero.name);
	 }
}

分析:当方法中的局部变量与实例变量同名时,在方法中如果不使用this前缀调用实例变量,则在方法中默认调用方法中的局部变量(形参也是局部变量

示例:实例变量与句变量同名(实例变量前有this

public class Hero {
	 String name;

	 public void setName(String name){
		 this.name=name; 
	 }
	 public  static void main(String[] args){
		 Hero hero=new Hero();
		 hero.setName("风暴精灵");
		 System.out.println("hero的名字为:"+hero.name);
	 }
}

2.2.3 实践练习

2.3 隐藏和封装

现实生活中的封装

隐藏内部实现细节,封装系统(部件、组件)功能

2.3.1 封装

封装是面向对象的三大特性之一

封装对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法实现对内部信息的操作和访问

封装是面向对像编程语言对客观世界的模拟,客观世界中的属性均被隐藏在对象内部,外界无法直接操作和修改

一个良好的封装可以实现以下目的:

隐藏类的实现细节

使用者只能通过事先预定的方法访问数据,从而可以在该方法中加入控制逻辑,限制对属性的不合理访问。

进行数据检查,从而有利于保证对象信息的完整性

便于修改,提高代码的可维护性

实现良好封装的途径:

隐藏对象的属性和实现细节,不允许外部直接访问

暴露出方法,让方法控制对这些属性进行安全的访问和操作

封装实际上有两个方面的含义:隐藏该隐藏的,暴露该暴露

Java封装的实质:使用访问控制符private隐藏属性,以及public暴露方法。

示例:利用封装隐藏英雄属性以及暴露属性赋值和更新的方法

public class Hero {
	//使用private修饰属性,隐藏这些属性
	private String name;
	private int  age;

	//public方法公开对name属性赋值
	public void setName(String name) {
		//执行合理校验,要求用户名必须在2~6之间
		if(name.length()>6||name.length()<2){
			System.out.println("您输入的名字不符合要求");
			return;
		}else{
			this.name = name;
		}
	}
	//public方法公开对name属性取值
	public String getName() {
		return name;
	}
	......
}

2.3.2 Java访问控制符

Java通过修饰符来控制类、属性和方法的访问权限和其他功能,通常放在语句的最前端。

Java支持四种不同的访问权限。

访问控制级别图:

Java访问控制级别表:

访问修饰符

同一个类中

同一个包中

子类中

所有类中

private

default

protected

public

示例:private访问控制符修饰的属性在同一个类中可以访问

public class Person{
   private String name="李彦宏";  
 
   public static void main(String args[]){
       Person person = new Person();
       //同一类中可以访问所有属性
       System.out.println("姓名是:"+person.name); 
   }
}

示例:default访问控制符修饰的属性在同一个包中可以访问

package com.vo;   
public class Person{
   //默认修饰符为default
   String name="李彦宏"; 
}
 

public class Test{
    public static void main(String args[]){
        Person person = new Person();
        //访问default修饰的属性
        System.out.println(person.name);  
    }
}

示例:default访问控制符修饰的属性在同一个包中可以访问

package com.vo;   
public class Person{
   //默认修饰符为default
   String name="李彦宏"; 
}
 

public class Test{
    public static void main(String args[]){
        Person person = new Person();
        //访问default修饰的属性
        System.out.println(person.name);  
    }
}

示例:public访问控制符修饰的属性能够被不同包中的类访问

package com.vo;   
 
public class Person{
      //public为公有访问修饰符      
      public String name="李彦宏";
}
 
package com.test;   
public class Test{
       public static void main(String args[]){
                Person person = new Person();
                 //被public修饰的属性在任何位置均可访问
               System.out.println(person.name);
      }
}

2.3.3 实践练习

2.4 static关键字

  • Java类的运行包括类加载和实例化两个阶段。
  • 一个类被加载至 JVM 中,静态成员会被初始化。
  • 静态成员不属于某个对象,仅属于静态成员所在的类。

static 修饰的成员即为静态成员。

静态代码

静态属性

静态方法

2.4.1 静态成员变量

静态成员变量属于其所在类,被类中的所有实例共享

静态成员变量可通过类直接访问,也可通过类的实例访问

示例:模拟个人银行账户取款10

public class Bank {
	//静态成员变量,账户余额
	private static int count = 50000 ;
	public static void main(String[] args) {
	            //实例化10个Bank对象		
	            for(int i=0; i<10; i++){
		   Bank bank=new Bank();
		   //每次取款1000元,类的实例调用静态成员属性
		   bank.count = bank.count - 1000;
		  //Bank.count=Bank.count-1000; //通过类名之间访问静态成员
		   System.out.println("当前银行总钱数="+Bank.count);
	        }
	}。
}

所有静态成员变量都可以通过直接访问。

2.4.2 静态方法

  • static修饰的方法称为静态方法
  • 静态方法也可通过类名直接访问,也可通过对象名访问。
  • 静态方法中不能访问非静态的成员,如实例属性、实例方法
  • 静态方法通常作为工具方法因为静态方法不会因为实例的不同,而影响方法最终的执行效果

示例:定义一个计算平方的静态方法

public class MathUtils {
	//计算平方
	public static double square(double num){
		return num*num;
	}
    public static void main(String[] args){
    	double num=9.6;
    	double result=MathUtils.square(num);
    	System.out.println(num+"的平方="+result);
    }
}

为什么静态方法不能访问非静态成员?

Java程序运行时首先由JVM加载类。

加载时会为静态的成员开辟内存空间,而实例成员在类的实例化       阶段才被创建,所以当类加载时静态的成员已经被创建,而此时并不存在实例成员,因此不能在静态方法中访问非静态成员

但是实例方法可以访问静态成员。

2.4.3 静态代码块

  • 如果需要在类加载时执行某一操作,则可以使用静态代码
  • 静态代码不存在任何方法体中,它在Java虚拟机加载类时执行
  • 如果类中包含多个静态代码块,则Java虚拟机将按照它们在类中出现的顺序依次执行
  • 静态代码块只会被执行一次

为什么需要静态代码块?什么场合需要用到静态代码块?

静态方法在类加载后,虽然在内存中已经分配了内存空间,但只有显式地调用静态方法时,该方法才会被执行。如果需要在类加载时执行某一操作,则可以使用静态代码块

示例:静态代码块程序演示

public class StaticBlock {
	//第一个静态代码块
	static{
		System.out.println("---第一个静态代码块---");
	}
	//第二个静态代码块
	static{
		System.out.println("---第二个静态代码块---");
	}
	//第三个静态代码块
	static{
		System.out.println("---第三个静态代码块---");
	}
              public static void main(String[] args){
    	        System.out.println("---main方法被执行了---");
              }
}

虽然main()方法是程序的入口方法,但该方法是在类加载完成后,由JVM虚拟机调用该方法

静态代码块是在类加载就执行。

加载完静态代码块后才执行main()方法。

2.4.4 实践练习

总结:

  • 变量可以分为成员变量和局部变量,成员变量是在类范围定义的变量,局部变量是在方法中定义的变量
  • 成员变量分为类属性和实例属性两种,定义属性时没有static修饰符修饰的就是实例属性类属性的作用域与该类的生命周期相同例属性的作用域与其对应的实例的生命周期相同
  • this关键字代表自身。
  • 封装将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法实现对内部信息的操作和访问
  • Java访问控制符可见性范围由小到大为:private->default->protected->public
  • 静态成员变量属于其所在类,被类中的所有实例共享,静态成员变量可通过类直接访问,也可通过类的实例访问静态方法不能访问非静态的成员

猜你喜欢

转载自blog.csdn.net/weixin_44893902/article/details/106001911