1、封装:隐藏事物的属性和实现细节,对外提供公共的访问方式。
2、封装的好处:
隐藏了事物的实现细节
提高了代码的复用性
提高了安全性
3、封装的原则:
隐藏事物的属性
隐藏事物的实现细节
对外提供公共的访问方式
1、private单词:私有的
2、可以修饰的内容:
修饰成员变量
修饰成员方法
修饰构造方法
3、修饰之后的效果:
被private修饰的成员,只能在本类中被访问。
4、private关键字的注意事项;
private只是封装的一种体现形式
1、当属性被私有之后,外界无法直接访问,所以需要提供公共的访问方式,让外界可以间接的访问属性。对于当前类,就可以控制外界访问属性的方式。(我让你怎么访问,你就只能怎么访问)
2、一般提供get方法,获取成员变量的值、提供set方法,设置成员变量的值
1、变量访问的就近原则:
就近原则:当在访问某个变量名称的时候,会先寻找最近的该变量名称的定义,如果寻找到了,就使用该变量,如果没有找到,才到更远的位置寻找该变量名称的定义。
当局部变量和成员变量同名的时候,一定是先使用局部位置定义的变量,如果没有,才会使用成员位置定义的变量。
2、this关键字:
表示当前类型当前对象的引用
哪个来调用this所在的方法,this就代表哪个对象
作用:用于区分局部变量和成员变量同名的情况。使用this.属性名称的一定是成员变量,没有使用this.的变量,根据就近原则来确定使用哪个变量。
代码示例:
class Student {
private String name;
private int score;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public void test(String[] args) {
String name;
name = "张三";//指的是局部变量name
}
}
1、构造方法:构造函数,构造器,Constructor
2、作用:用于给对象中的成员变量赋值。在创建对象的同时,会自动调用构造方法,等对象创建完成的时候,对象中的成员变量就已经有指定的值了。
3、构造方法的定义格式:
修饰符 方法名称(参数列表) {
方法体
}
4、构造方法格式的说明:
1、构造方法的方法名称,必须和类名一模一样,连大小写都一样。
2、构造方法没有返回值类型,连void也没有
3、构造方法没有return语句,如果一定需要return语句,就写一个return;
return后面不能跟 内容,加return没有实际的意义。
5、构造方法其他说明:
1、构造方法不需要手动调用,由jvm虚拟机在创建对象的时候自动调用
2、对象本身不能调用构造方法
3、构造方法只调用一次。
1、构造方法可以是有参数的,也可以是没有参数的
如果是没有参数的构造方法,外界无需传入任何的参数值,只能给成员变量赋固定值或者不赋值
如果是有参数的构造方法,外界在调用构造方法的时候,需要传入实际的参数值,用于赋值给成员变量。
2、如果在类中没有定义任何的构造方法,那么系统会自动提供一个空参构造(空实现)
3、如果在类中手动定义了一个构造方法(无论是空参还是有参),系统都不再会提供任何的构造方法。
4、构造方法的重载:
在同一个类中,方法名相同,参数列表不同,与返回值类型无关
1、构造方法和set方法都是用于给成员变量赋值。二者都不希望外界直接访问私有成员变量,通过构造方法或者set方法,间接的访问私有变量。
2、区别:
构造方法是在创建对象的同时,由jvm自动调用执行,用于给属性赋值,只能执行一次
set方法是在创建对象之后,由对象手动调用执行,用于给属性修改值,可以调用多次
3、使用场景比较:
一般set方法使用更加灵活,使用更加频繁
构造方法,只能在创建对象的时候被自动调用一次,代码更加简洁。一旦对象创建成功,就不能继续使用构造方法修改成员变量的值。
1、没有静态:如果某个类型的所有对象,都具有一个相同的属性值,比如2个对象的age都是23;
那么这个属性值就没有必要在所有对象中,都存储一份。
坏处:浪费内存空间;维护难度大,一旦需要修改,就得修改所有的对象。
public class Test01 {
public static void main(String[] args) {
Actor a1 = new Actor();
a1.name = "张三";
a1.country = "中国";
System.out.println(a1.name + "..." + a1.country);
Actor a2 = new Actor();
a2.name = "李四";
a2.country = "中国";
System.out.println(a2.name + "..." + a2.country);
//二者都来自中国
}
}
class Actor {
String name;
String country;
}
2、有静态的状态:如果某个类型的所有对象,都具有一个相同的属性值,那么就在这个属性的定义上,加一个static静态关键字。让该变量存储在方法区字节码的静态区中,避免了所有对象都存储相同数据的问题,节省了内存空间,将来维护容易(只需要修改一次)
/**
* 有静态代码示例
*/
public class Simple02 {
public static void main(String[] args) {
Actor1 a1 = new Actor1();
a1.name = "张三";
a1.country = "中国";
System.out.println(a1.name + "..." + a1.country);//张三 中国
Actor1 a2 = new Actor1();
a2.name = "李四";
a2.country = "中国";
System.out.println(a2.name + "..." + a2.country);//李四 中国
Actor1.country = "法国";
System.out.println(a1.name + "..." + a1.country);//张三 法国
System.out.println(a2.name + "..." + a2.country);//李四 法国
}
}
class Actor1 {
String name;
static String country;//加上static关键字
}
1、静态的解释:static关键字
静态、静止的。静态变量不会随着对象的变化而变化
2、加载时机:
随着类的加载而加载。
静态变量随着类的加载进方法区,就直接在静态区给开辟了存储静态变量的内存空间
3、静态变量优先于对象而存在
4、静态变量被所有该类对象所共享
5、代码层面:可以使用类名直接调用,不需要使用对象名称。在不创建对象的前提下,仍然可以使用这个静态变量。建议使用类名来访问。
1、静态方法:在方法声明上,加上了static关键字的方法,就是静态方法
2、静态方法不能访问非静态的变量
原因:静态方法本身可以在没有创建对象的时候调用;非静态的变量只有在对象创建之后才存在。如果静态方法可以访问非静态的变量,那么就相当于在对象创建之前,就访问了对象创建之后的数据。明显不合理。
3、静态方法不能访问非静态的方法
原因:静态方法可以在没有创建对象的时候调用;非静态的方法可以访问非静态的变量。如果静态方法可以访问非静态的方法,就相当于静态方法间接的访问了非静态的变量
4、静态方法中不能存在this关键字
原因:this关键字表示本类当前对象。静态方法可以在对象创建之前调用。如果静态方法可以访问this关键字,相当于在创建对象之前,就使用了对象本身。矛盾。
5、总结:
静态不能访问非静态
1、概念上,所属不同:
非静态变量属于对象
静态变量属于类,类变量
2、内存空间不同,存储位置不同
非静态变量属于对象,所以存储在堆内存中
静态变量属于类,存储在方法区的静态区中
3、内存时间不同,生命周期不同
非静态变量属于对象,所以生命周期和对象相同,随着对象的创建而存在,随着对象的消失而消失
静态变量属于类,所以生命周期和类相同,随着类的加载
4、访问方式不同
非静态变量只能使用对象名访问
静态变量既可以使用对象访问,也可以通过类名访问:
类名.静态变量名
类名.静态方法名()
1、工具类:在一个类中,没有维护什么数据,没有任何的成员变量,相当于是一个工具。类中就都是一些静态方法,快速的解决一些常见的问题。
2、名称:ArrayTool
3、作用:可以提供操作数据的各种方法
4、功能:
数组的遍历
获取数组的最大值
获取数组的最小值
数组元素反转
5、方法都是静态的,不需要创建对象;创建对象会浪费系统资源。希望控制不让创建对象。
方式:使用构造方法私有化
代码示例:
public class ArraysUtil
// 1、循环打印数组
public static void print(int[] arr) {
for (int i = 0; i < arr.length; i++) {
if (arr != null) {
System.out.print(arr[i] + ",");
}
}
}
// 2、循环打印数组,一行打印指定个数的元素
public static void print(int[] arr, int number) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + ",");
if ((i + 1) % number == 0) {
System.out.println();// 换一行
}
}
}
// 3、将数组转成[元素1,元素2...]这种格式的字符串
public static String formatPrint(int[] arr) {
if (arr == null)
return "null";
int iMax = arr.length - 1;// 如果iMax是-1 意味着数组长度是0
if (iMax == -1)
return "数组长度为0";
StringBuilder b = new StringBuilder();//
b.append('[');// 在最前方追加一个[
for (int i = 0;; i++) {
b.append(arr[i]);
if (i == iMax) {// 满足条件 就退出
return b.append(']').toString();
}
b.append(", ");
}
}
// 4、将数组冒泡\或者其他算法排序(直接将原数组排序)
public static void sort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int desk = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = desk;
}
}
}
}
// 5、将数组冒泡\或者其他算法排序(不允许排形参的数组,需要直接返回一个排好序的新数组)
public static int[] sortNew(int[] arr) {
int arrNew[] = new int[arr.length];
// 把源数组 内容赋值一份给 arrNew
// arrNew = Arrays.copyOf(arr, arr.length);
for (int i = 0; i < arrNew.length; i++) {
arrNew[i] = arr[i];
}
for (int i = 0; i < arrNew.length - 1; i++) {
for (int j = 0; j < arrNew.length - 1 - i; j++) {
if (arrNew[j] > arrNew[j + 1]) {
int desk = arrNew[j];
arrNew[j] = arrNew[j + 1];
arrNew[j + 1] = desk;
}
}
}
return arrNew;
}
// 6、比较两个数组的所有元素是否完全一致
public static boolean isEquals(int[] arr1, int[] arr2) {
if (arr1 == arr2)// 地址相同 里面的数据肯定相同
return true;
if (arr1 == null || arr2 == null)
return false;
int length = arr1.length;
if (arr2.length != length)
return false;
for (int i = 0; i < length; i++)
if (arr1[i] != arr2[i])
return false;
return true;
}
// 7、计算数组的平均值
public static double avg(int[] arr) {
double sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum / arr.length;
}
// 8、计算数组的最大值
public static int max(int[] arr) {
int maxnumber = arr[0];// 数组第一个 为最大值
for (int i = 1; i < arr.length; i++) {
if (maxnumber < arr[i]) {
maxnumber = arr[i];
}
}
return maxnumber;
}
// 9、计算数组的最小值
public static int min(int[] arr) {
int minnumber = arr[0];// 数组第一个 为最小值
for (int i = 0; i < arr.length; i++) {
if (minnumber > arr[i]) {
minnumber = arr[i];
}
}
return minnumber;
}
// 10、将一个数组的所有元素都反转(比如{5,4,8}变成{8,4,5})
public static int[] reverse(int[] arr) {
int[] arrNew = new int[arr.length];
for (int x = 0; x < arr.length; x++) {
arrNew[x] = arr[arr.length - 1 - x];
}
return arrNew;
}
// 11、判断一个指定的数值在数组中是否存在
public static boolean isExits(int[] arr, int number) {
boolean isTrue = false;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == number) {
return true;
}
}
// 如果不存在
return false;
}
}