文章目录
一、封装1.1 封装的概念1.2 访问限定符1.3封装扩展之包 二、static成员2.1static关键字的引入2.2静态成员变量初始化2.3访问静态成员变量2.4用实际问题加深静态成员变量的理解2.5静态成员变量的总结要点2.6静态成员方法的总结要点 三、代码块3.1普通代码块3.2构造代码块3.3静态代码块3.4代码块的总结要点
前言:
面向对象程序三大特性:封装、继承、多态。本篇博客主要整理了面向对象之封装的概念,四种访问限定符,包的概念及创建包的操作,包访问权限控制举例,静态成员变量,静态成员方法,静态成员变量的初始化,代码块
一、封装
1.1 封装的概念
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互
Java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,更符合人类对事物的认知,而访问权限用来控制方法或者字段能否直接在类外使用。
1.2 访问限定符
Java中提供了四种访问限定符:private
、default
、protected
、public
private
:只能在当前类使用
default
:使用这个限定符,什么也不加,代表是包访问权限,只能在当前包中被访问
protected
:可以在同一个包中被访问,或者不同包中的子类中可以被访问(需要注意的是,在修饰变量或方法时并不是在前面写上default,而是什么也不写)
public
:同一个包,不同的包中都可以被访问
代码示例如下:
public class Test { class Animal { public String name;//可以被公开访问和使用 String color;//包访问权限,只能在同一个包中被访问 private int age;//只能在当前类中被访问 protected String sex;//在当前包中被访问,或者在当前类的子类中被访问 }}
1.3封装扩展之包
包的概念
包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,比如:一个包中的类不想被其他包中的类使用。包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在不同的包中即可
导入包中的类
我们常说的导包,其实是导入包中的某个类。比如要使用Scanner
类创建一个对象时,需要用import
导入这个类。这里的 java.util
就是类所在的包, Scanner
就是用到的类。
public class Test {public static void main(String[] args) { java.util.Scanner scan = new java.util.Scanner(System.in); }}
但是这样写比较麻烦,可以使用import
语句导入包
import java.util.Scanner;public class Test {public static void main(String[] args) { Scanner scan = new Scanner(System.in); }}
通配符 *
使用通配符,import java.util.*
,如果用到了util
底下的某个类,就会加载相对应的类,所以不用担心一次把里面所有类全部加载完
如果要使用java.util
中的多个类甚至所有类,可以使用import java.util.*
,但是不推荐,容易出现冲突的情况,比如以下代码:
import java.util.*;import java.sql.*;public class Test {public static void main(String[] args) {// util 和 sql 中都存在一个 Date 这样的类, 此时就会出现歧义, 编译出错 Date date = new Date(); System.out.println(date.getTime());}}
编译出错
对Date的引用不明确java.sql
中的类 java.sql.Date
和 java.util
中的类 java.util.Date
都匹配
在这种情况下应该使用完整的类名,代码示例如下:
import java.util.*;import java.sql.*;public class Test {public static void main(String[] args) { java.util.Date date = new java.util.Date(); System.out.println(date.getTime());}}
自定义包
基本规则
代码.如果一个类没有 package 语句, 则该类被放到一个默认包中.
操作步骤
右键src,选择New,再点击Package
输入包的名称,回车(注意包名应全部为小写字母)
此时可以看到我们的磁盘上的目录结构已经被 IDEA 自动创建出来了
同时我们也看到了, 在新创建的 Test.java 文件的最上方, 就出现了一个 package 语句,说明Test类所在的包
包的访问权限控制举例
如果在www这个包里面创建一个Test1类,类内部定义有 包访问权限的age
,在不同包 demo包中创建一个Test2类,那么对于age
来说 在不同包中Test2类就不能访问age
,只能在demo这个包中被访问
二、static成员
成员变量分为 静态成员变量 和 实例成员变量
2.1static关键字的引入
static修饰成员变量
以学生类进行举例,代码示例如下
public class Student{ public String name; public String sex; public int age; public Student(String name,String sex,int age) { this.name = name; this.sex = sex; this.age = age; }public static void main (String[] args) { Student stu1 = new Student ("张三","男",18); Student stu2 = new Student ("李四","男",19);}}
以Student
类创建两个学生对象,那么如果这两个学生都在同一个教室403上课,或者有100个学生对象都在403教室上课,是不是要再加入一个public
修饰的classroom
的成员变量,并且在每次实例化学生对象时,都要输入相同的教室403?如果有非常多的学生,这样会造成大量重复的输入,那么就体现了static
关键字的作用了,我们只需定义一个静态成员变量classRoom
,这个成员变量前用static
进行修饰,说明这个变量是属于类的变量,不依赖于对象,是所有对象共享的,随类的加载而加载,生命周期随类的创建而被加载,随类的卸载而销毁。
代码示例如下
public class Student{ public String name; public String sex; public int age; public static String classRoom = "403";//就地初始化 public Student(String name,String sex,int age) { this.name = name; this.sex = sex; this.age = age; }public static void main (String[] args) { Student stu1 = new Student ("张三","男",18); Student stu2 = new Student ("李四","男",19);}}
2.2静态成员变量初始化
注意:静态成员变量一般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性
就地初始化:在定义时,直接给出初始值静态代码块初始化:下面会提及…2.3访问静态成员变量
在其类外使用时需要用类名进行访问,但也可以用当前对象的引用进行访问,但是这种方法不合理。
使用类名访问,代码示例如下
Student.classRoom = 306;System.out.println(Student.classRoom);
2.4用实际问题加深静态成员变量的理解
阅读以下代码,变量count
的最终值为多少? class TestStatic { public static int count = 10; public static void main(String[] args) { TestStatic testStatic1 = new TestStatic(); testStatic1.count++; TestStatic testStatic2 = new TestStatic(); testStatic2.count++; TestStatic testStatic2 = new TestStatic(); testStatic2.count++; TestStatic.count--; System.out.println(count); }}
count
的最终值为12,count
被static
修饰,说明count
为静态成员变量,属于类的变量,不管实例化多少个对象,count
也只有独一份,而这一份是随第一次类的加载而创建的,随后对count
的多次操作,都是针对这唯一一个count
操作的。
阅读以下代码,变量
age
是否能被打印,打印的数是多少?为什么? class Person { public static int age;}public class Test{ public static void main(String[] args) { Person person = null; System.out.println(person.age); }}
能被打印,打印的值为10,;age
是静态成员变量,不依赖于对象,属于类的变量;Person person = null
说明person
引用不指向任何的对象,而age
本身就独立于对象,所以访问age
和person
引用所指的对象为不为空 没有关系,因为age
是类的变量,不在对象里
2.5静态成员变量的总结要点
被static
修饰的成员变量属于类的变量,储存在方法区中,随类的加载而被加载,不再属于对象,不再依赖于对象。静态成员变量不属于某个对象,是类的属性,是多个对象共享的,即使创建多个对象也不会新增第二个静态成员变量。在其类外使用时需要用类名进行访问,但也可以用当前对象的引用进行访问,但是这种方法不合理。生命周期伴随类的一生:随类的加载而创建,随类的卸载而销毁。(当用类名进行访问类的属性时,类就会被加载,进而这些静态成员变量就会被创建)方法中不能定义和使用静态成员变量,在方法当中定义的变量是局部变量,而静态的变量属于类变量。随着类的加载而被创建,而局部变量是调用该方法的时候,才创建的。所以,此时两种变量的性质是冲突的。Java当中不允许定义局部的静态变量 static修饰成员方法
Java中,被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。静态成员一般是通过
静态方法来访问的。代码示例如下:
public class Student{ // ... private static String classRoom = "306"; // ... public static String getClassRoom(){ return classRoom; }} public class TestStudent { public static void main(String[] args) { System.out.println(Student.getClassRoom()); }}
输出:306
2.6静态成员方法的总结要点
静态成员方法不属于某个具体的对象,属于类的方法。要用类名的方式调用,也可以用当前对象的引用进行调用,但是这样调用不合理静态成员方法里面不能任何访问非静态的成员变量或成员方法,也不能出现this
参数,因为这些都是依赖于对象的,而静态成员方法属于类的方法,不依赖于对象 三、代码块
代码块用来初始化成员变量,
实例(构造)代码块:一般用来初始化实例成员变量(非静态成员变量)
静态代码块:一般用来初始化静态成员变量
3.1普通代码块
定义在方法中的代码块,使用{ }
定义,代码示例如下:
public class Main{ public static void main(String[] args) {{ //直接使用{}定义,普通方法块 int x = 10 ; System.out.println("x1 = " +x);} int x = 100 ; System.out.println("x2 = " +x);}}
运行结果:x1 = 10
x2 = 100
这种用法比较少见
3.2构造代码块
也叫实例代码块,一般用来初始化实例成员变量(非静态成员变量);定义在类的里面,方法的外面,
使用{}
定义,代码示例如下:
public class Student{ public String name; public int age; public static String classRoom = "403";//就地初始化 public Student(String name,int age) { System.out.println("构造方法"); this.name = name; this.age = age; } { age = 16; System.out.println("构造代码块"); }public static void main (String[] args) { Student stu1 = new Student ("张三",18); System.out.println(stu1.age);}}
运行结果:
构造代码块
构造方法
18
运行结果说明,先执行构造代码块,后执行构造方法
3.3静态代码块
一般用来初始化静态成员变量;定义在类的里面,方法的外面,
使用static {}
定义,代码示例如下:
public class Student{ public String name; public int age; public static String classRoom = "403";//就地初始化 public Student(String name,int age) { System.out.println("构造方法"); this.name = name; this.age = age; } { age = 16; System.out.println("构造代码块"); } static { classRoom = "309"; System.out.println("静态代码块"); }public static void main (String[] args) { Student stu1 = new Student ("张三",18); System.out.println(Student.classRoom);}}
运行结果:
静态代码块
构造代码块
构造方法
309
运行结果说明,执行顺序:静态代码块 > 构造代码块 > 构造方法
另外若有多个静态代码块,执行顺序按照定义代码的先后顺序执行,且静态代码块只会被执行一次