封装:
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互
封装拓展包::
在面向对象体系中,提出了一个软件包的概念,即:为了更好的管理类,把多个类收集在一起成为一组,称为软件包。有点类似于目录。
这些包是什么呢?就要找到相关路径,java.util路径底下。
这个文件夹需要在jdk中找到src底下的java中的util中:
最后找到Scanner类,可以打开看:
其实也是一个定义类,用的时候需要导包,然后实例化对象使用!!
自定义包:
当然我们也可以进行一个简单的创建包,在包中定义类,需要的时候可以导包使用。
1、创建包:
2、给包起名字:
定义一个类:
当我在其他包中调用该类的时候就会出现:
红色的提示!!!!
所以此时有两种解决方案:
1、在实例化的时候,直接写清楚该类的路径:
2、导包!!
导入该类的具体路径!
访问限定符:
public :可以理解为一个人的外貌特征,谁都可以看得到default: 对于自己家族中 ( 同一个包中 ) 不是什么秘密,对于其他人来说就是隐私了private :只有自己知道,其他人都不知道
包的访问权限:
那么问题是:刚刚举的Date的例子当中,我可以在其他包中的方法中实例化Date,且大家有没有注意到我在构建Date的时候不论是成员变量还是构造方法,我都使用的是public开头。
那如果将其中的一些改为private会是什么样的结果呢?
public class Date { private int year; private int month; private int day; public Date(int year,int month,int day){ this.day = day; this.month = month; this.year = year; System.out.println(year+" "+month+" "+day); } private void setDate(int x){ year = x; } }
将类的成员变量都改为私有的,将其中的一个方法改为私有的。
发现虽然我导入相关的包了,也可以实例化对象,但是就是调用不了对象中的private修饰的变量和方法!
这里就体现了封装的意义,我们一般构建类的时候都是将其成员变量进行私有化,然后类中的方法式公开的,所以想要对对象中的成员变量进行修改的话,只能借助类中的方法。
public int getYear() { return year; } public void setYear(int year) { this.year = year; } public int getMonth() { return month; } public void setMonth(int month) { this.month = month; } public int getDay() { return day; } public void setDay(int day) { this.day = day; }
这里行代码就可以对类中的成员变量进行赋值并且如果需要也可以打印出来。
(对成员变量进行保护)
当然大家可以去试试其他的访问限定符!!!!
static成员:
static修饰的成员变量:
如果一个成员变量被static修饰会带来什么样的影响?
可以以一个类举例:
class Dog{ public String name; public String color; public void barks(){ System.out.println("汪汪汪!"); } public Dog(){ System.out.println("这是一只构造方法的狗"); } }还是拿Dog这个类来举例。
此时在main方法中实例化对象:
通过调试发现这只狗的这两个成员变量是存在的。
那如果在成员变量前+static会是怎样的呢?
继续调试观察:
发现很严重的问题,成员变量不见了!!!
成员变量去哪了?
那此时我能不能调用成员变量呢?
揭开面纱:
static 修饰的成员变量,称为静态成员变量 ,静态成员变量最大的特性: 不属于某个具体的对象,是所有对象所共 享的 。
【静态成员变量特性】1. 不属于某个具体的对象,是类的属性,所有对象共享的, 不存储在某个对象的空间中2. 既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问3. 类变量存储在方法区当中4. 生命周期伴随类的一生 ( 即:随类的加载而创建,随类的卸载而销毁 )
真相大白,原来被static修饰的成员变量放在了方法区中,进而成了共享成员。
既然是共享成员的话,那当然可以调用的。
发现还是可以修改的,只不过这里推荐用类名直接访问。
那如果我不去实例化对象可不可以访问呢?
发现了!!还是可以访问滴。(相当于直接可以对类中的成员变量就地初始化)
static修饰成员方法:
static修饰成员方法,其实和static修饰成员方法是一样的,一般静态成员变量是通过静态成员方法进行访问!
public class Student {// ...private static String classRoom = "Bit306" ;// ...public static String getClassRoom (){return classRoom ;}}public class TestStudent {public static void main ( String [] args ) {System . out . println ( Student . getClassRoom ());}}
输出:Bit306
【 静态方法特性 】1. 不属于某个具体的对象,是类方法2. 可以通过对象调用,也可以通过类名 . 静态方法名 (...) 方式调用,更推荐使用后者3. 不能在静态方法中访问任何非静态成员变量4.静态方法中不能调用任何非静态方法,因为非静态方法有 this 参数,在静态方法中调用时候无法传递 this 引用
public static String getClassRoom (){System . out . println ( this );return classRoom ;}// 编译失败: Error:(35, 28) java: 无法从静态上下文中引用非静态 变量 thispublic static String getClassRoom (){age += 1 ;return classRoom ;}// 编译失败: Error:(35, 9) java: 无法从静态上下文中引用非静态 变量 age
static成员变量初始化:
1 静态成员变量的初始化分为两种:就地初始化 和 静态代码块初始化。
public class Student {private String name ;private String gender ;private int age ;private double score ;private static String classRoom = "Bit306" ;// ...}
2. 静态代码块初始化
代码块:
代码块概念以及分类 :
使用 {} 定义的一段代码称为代码块 。根据代码块定义的位置以及关键字,又可分为以下四种:普通代码块构造块静态块同步代码块(后续讲解多线程部分再谈)
普通代码块:
普通代码块:定义在方法中的代码块。
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 = 10x2 = 100
代码块里面的x和外边定义的x是不一样的!(括号里面的是局部变量!)
构造代码块:
class Dog{ public String name; /** * 构造代码块 */ public String color; { this.name = "huahua"; this.color = "black"; System.out.println( "instance init()"); } public void barks(){ System.out.println(name+"汪汪汪!"); } public Dog(){ System.out.println("这是一只构造方法的狗"); } //该方法赋值失效 public static void setDog(String name,String color){ // name = name; // color = color; }
那么初始化结束了,那么如果实例化对象之后,究竟是先打印代码块里面的内容?还是先打印构造方法的内容呢?
如果构造块放在构造方法的前面时:
发现先打印的时构造方法里面的内容!!
所以综上:
先打印是代码块,之后就再打印构造方法的内容!!
那么如果交换一下顺序呢?
class Dog{
public String name;
/**
* 构造代码块
*/
public String color;
public void barks(){
System.out.println(name+"汪汪汪!");
}
public Dog(){
System.out.println("这是一只构造方法的狗");
}
{
this.name = "huahua";
this.color = "black";
System.out.println( "instance init()");
}
}
发现没有变化,所以综上:
打印的顺序为;代码块、构造方法!
静态代码块:
使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量。
class Dog{
public String name;
public static String color;
public void barks(){
System.out.println(name+"汪汪汪!");
}
public Dog(){
System.out.println("这是一只构造方法的狗");
}
//构造代码块
{
this.name = "huahua";
System.out.println( "instance init()");
}
//静态代码块
static{
color = "black";
System.out.println("static instance init()");
}
}
那么打印顺序又会是怎么样的呢?
此时发现还是先打印代码块的内容,究竟是先打印那个代码块呢?
此时交换两个代码块:
class Dog{
public String name;
public static String color;
public void barks(){
System.out.println(name+"汪汪汪!");
}
public Dog(){
System.out.println("这是一只构造方法的狗");
}
//静态代码块
static{
color = "black";
System.out.println("static instance init()");
}
//构造代码块
{
this.name = "huahua";
System.out.println( "instance init()");
}
}
综上:
实例化对象之后的打印顺序:
静态代码块 -> 构造代码块 -> 构造方法!!
注意事项静态代码块不管生成多少个对象,其只会执行一次静态成员变量是类的属性,因此是在 JVM 加载类时开辟空间并初始化的如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行 ( 合并 )实例代码块只有在创建对象时才会执行