目录
面向对象语言的三大特性:封装、继承、多态。本篇文章将讲述封装有关...何为封装?! 简而言之就是套壳屏蔽细节...
概念
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
注:接口有两层含义 -> ①.方法 ②.真正的接口(语法);此处加粗的接口为第一层含义
如下列代码,将成员变量name,age用private修饰后,外界不可直接获取、修改name和age,那么通过创建公开的方法getName()、setName()、getAge()...来对封装的成员变量进行操作
public class Person {
private String name;
private int age;
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
}
Person person = new Person();
person.setName("张三");
System.out.println(person.getName());//打印张三
●快捷生成get()/set()方法 --> 鼠标右键Generate --> Getter(只要get())
Setter(只要set()) --> 可选中全部属性
Getter and Setter
--> ok --> 会自动生成get()/set()
因此,从语法上来说,封装就是被private修饰的成员变量或者成员方法,且只能在当前类当中使用。
访问限定符
JAVA中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,而访问权限用来控制方法或者字段能否直接在类外使用。
JAVA提供了四种访问限定符:
No | 范围 | private | default | protected | public |
1 | 同一包中的同一类 | ✔ | ✔ | ✔ | ✔ |
2 | 同一包中的不同类 | ✔ | ✔ | ✔ | |
3 | 不同包中的子类 | ✔ | ✔ | ||
4 | 不同包中的非子类 | ✔ |
private: 私有的(只有自己知道,其他人都不知道)
default: 默认的,包访问权限 (!不要在成员/方法前加default,什么都不写即为默认)
protected: 受保护的 (主要用在继承中,继承部分详细介绍)
public: 公有的(哪都能用)
注:①.访问权限除了可以限定类中成员的可见性,也可以控制类的可见性
②.一般情况下,成员变量设置为private,成员方法设置为public
封装扩展之包
包的概念
为了更好的组织和管理类,把多个类收集在一起成为一组,称为软件包。
导入包中的类
●使用import语句导入包
eg:专门组织管理和操作数组相关的类
import java.util.Arrays
包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式。包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在不同的包中即可。
例如,Date类既存在于java.util包中,也存在于java.sql包中
import java.util.Date;
import java.sql.Date;
如果需要使用java.util中的其他类,可以使用通配符*
import java.util.*
(只要是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());
}
}
//编译出错
//Error:(5,9)java:对Date的引用不准确
//java.sql中的类java.sql.Date和java.util中的类java.util.Date都匹配
在这种情况下需要使用完整的类名
java.util.Date date = new java.util.Date();
●使用import static导入包中静态的方法和字段
import static java.lang.Math.*; //导入导入这个类中的所有静态方法
public class Test{
public static void main(String[] args){
double x = 30;
double y = 40;
//静态导入的方式写起来更方便一些
//double result = Math.sqrt( Math.pow(x,2) + Math.pow(y,2) );
double redult = sqrt( pow(x,2) + pow(y,2) );
System.out.println(result);
}
}
*归根结底,包就是个文件夹,里面有很多类,类中有很多方法...
自定义包
基本规则
● 在文件的最上方加上一个package语句指定该代码在哪个包中.
●包名需要尽量指定成唯一的名字,通常会用公司的域名的颠倒形式(eg: com.baidu.www;)
●包名要和代码路径相匹配。eg:创建com.baidu.demo1的包,那么会存在一个对应的路径 com/baidu/demo1来存储代码
●如果一个类没有package语句,则该类被放到一个默认包中.
操作步骤
1.先创建一个包:右键src --> 新建 --> 包
2.在弹出的对话框中输入包名(小写)
3.在包中创建类:右键包名 --> 新建 --> 类,然后输入类名即可
4.此时可以看到磁盘上的目录结构已经被IDEA自动创建出来了
5.同时可以看到,在新创建的Test.java文件的最上方,就出现了一个package语句
static成员
概念
使用学生类实例化三个对象s1、s2、s3,每个对象都有自己特有的姓名、性别、年龄、学分绩点等成员信息,这些信息就是对不同学生进行描述的,如下所示:
public class Student{
public static void main(String[] args){
Student s1 = new Student("李雷","男",18,3.8);
Student s2 = new Student("韩梅梅","女",19,4.0);
Student s3 = new Student("Jim","男",18,2.6);
}
}
假设三个同学是同一班的,那么他们上课肯定是在同一个教室,既然在同一个教室,能否在类中再加一个成员变量,来保存同学上课时的教室呢?!
答案是不行的 --> 在Student类中定义的成员变量,每个对象都会包含一份(称为实例变量),因为需要使用这些信息来描述具体的学生。而现在要表示上课的教室,这个教室的属性并不需要每个学生对象中都存储一份,而是需要让所有的学生来共享。
在JAVA中,被static修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对象,是所有对象所共享的。
static修饰成员变量
static修饰的成员变量,称为静态成员变量
[静态成员变量特性]:
①.不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中(最大特性,即静态成员变量不属于对象)
②.既可以通过对象访问(会出现警告),也可以通过类名访问(推荐)
③.类变量存储在方法区当中
④.生命周期伴随类的一生(随类的加载而创建,随类的卸载而销毁)
public class Student{
public static String classRoom = "101";
public static void main(String[] args){
//静态成员变量可以直接通过类名访问
System.out.println(Student.classRoom);
}
}
static修饰成员方法
一般类中的数据成员都设置为private,而成员方法设置为public,那设置之后,Student类中classroom属性如何在类外访问呢?!
public class Student{
private static String classRoom = "101";
}
public class TestStudent{
public static void main(String[] args){
System.out.println(Student.classRoom);
}
}
//Error:(10,35)java:classRoom在extend01.Student中是private控制
JAVA中,被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。静态成员一般是通过静态方法来访问的。
public class Student{
private static String classRoom = "101";
public static String getClassRoom(){
return classRoom;
}
}
public class TestStudent{
public static void main(String[] args){
System.out.println(Student.getClassRoom());
}
}
[静态方法特性]:
①.不属于某个具体的对象,是类方法
② .可以通过对象调用,也可以通过类名.静态方法名(...)方式调用(更推荐)
③.不能在静态方法中访问任何非静态成员变量
④ .静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用
eg:
public static void func(){
System.out.println("静态的!");
System.out.println(this.name + "。。。"); //error
}
-->name的调用需要对象的引用来调用,而func()这个静态方法直接通过类名就能调用,不依赖于对象 --> 因此,在静态方法中,不能调用非静态的成员变量或者非静态的成员方法;静态方法当中不包含this
static成员变量初始化
静态成员变量的初始化分为两种:就地初始化、静态代码块初始化
Ⅰ.就地初始化
就地初始化指的是:在定义时直接给出初始值
public class Student{
private String name;
private String gender;
//...
private static String classRoom = "101";
}
Ⅱ.静态代码块初始化
什么是代码块?!!
代码块概念及分类
使用{}定义的一段代码称为代码块,可分为以下四种:普通代码块、*构造块、*静态块、同步代码块
普通代码块
定义在方法中的代码块(很少见)
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
构造代码块
构造块:定义在类中的代码块(不加修饰符),也叫:实例代码块。
构造代码块
一般用于初始化实例成员变量
public class Student{
//实例成员变量
private String name;
private String gender;
{
this.name = "小明";
this.gender = "男";
}
public void show(){
System.out.println("name:" + name + "gender:" + gender);
}
}
public class Main{
public static void main(String[] args){
Student stu = new Student();
stu.show();
}
}
//name:小明gender:男
注:构造(实例)代码块只有在创建对象时才会执行
静态代码块
使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量。
public class Student{
private static String classRoom;
static{
classRoom = "101";
}
}
注:
●静态代码块不管生成多少个对象,其只会执行一次
●静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的
●如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(合并)
同步代码块
具体介绍在后续多线程部分...
总结
①.执行顺序:静态代码块 --> 构造代码块 --> 对应的构造方法
②.静态代码块只执行一次