一、变量的生命周期
成员变量: 全局变量/字段(Field), 直接定义在类中,方法外面.
1):类成员变量. 使用static修饰的字段.
2):实例成员变量. 没有使用static修饰的字段.
局部变量: 变量除了成员变量,其他都是局部变量.
1): 方法内部的变量.
2):方法的形参.
3):代码块中的变量,一对{}.
变量的初始值:初始化才会在内存中开辟空间.
成员变量: 默认是有初始值的
局部变量: 没有初始值,所以必须先初始化才能使用.
变量的作用域:
成员变量: 在整个类中都有效.
局部变量: 在开始定义的位置开始,到紧跟着结束的花括号为止.
成员变量,可以先使用后定义,局部变量必须先定义而后才能使用.
class ABC
{
String info = null;//成员变量
void doWork(String name)
{
System.out.println(x);
int age;//局部变量
if(true)
{
int num;//局部变量
}
}
String x ;
}
什么时候使用成员变量和局部变量:
1:考虑变量的生存时间,这会影响内存开销。
2:扩大变量作用域,不利于提高程序的高内聚。
开发中应该尽量缩小变量的作用范围,如此在内存中停留时间越短,性能也就更高。
不要动不动就使用static修饰,一般,定义工具方法的时候,static方法需要访问的变量,该变量属于类,此时才使用static修饰字段.
也不要动不动就使用成员变量,因为存在着线程不安全问题,能使用局部变量尽量使用局部变量。
二、package与import
关键字:package.
作用:专门用来给当前的java文件设置包名
语法格式:package 包名.子包;
//必须把该语句作为Java文件中,并且在第一行代码(所有代码之前)
//包名后也可以有子包…子子包…子子子包…等
如果此时java文件中使用了package语句,表示此时在当前目录中先生成包名,
再在包中生成class文件。
自定义的包名,不能以java.打头,因为Java的安全机制会检查。
package PcgB.pcg;//将会自动在目录中生成一个PcgB/pcg文件,其中就放置了该类的字节码文件。
public class PackageDemo
{
public static void main(String[] args)
{
System.out.println("Hello!");
}
}
JDK中各个包的功能
关键字:import
学习过的 数组的工具类:Arrays类,该类在java.util包中。Arrays类的全限定名:java.util.Arrays,当我们需要使用的时候,我们需要完整的输入它的路径名称,但是使用了import之后,就可以将这个工作简化。
语法格式: import 需要导入类的全限定名;
此后,在本Java文件中,只需要使用类的简单名称即可.
/*
import java.util.Arrays;
import java.util.Set;
import java.util.List;
*/
//上述代码分别表示引入了java.util包下的Arrays类,Set类,List类
//问题:如果我们还需要引人其他类,我们还需要提供N个import语句
/*
解决方案:使用通配符 *
*/
//语法格式: import 导入类的全限定名;
import java.util.*;
class ImportDemo
{
public static void main(String[] args)
{
int[] arr = new int[] {2,1,3,4,5,6};
//打印数组
String ret = Arrays.toString(arr);
//排序
Arrays.sort(arr);
ret = Arrays.toString(arr);
//打印
System.out.println(ret);
//没有使用import之前,操作不在同一包中的类,要使用全限定名操作。
//解决方案:直接使用import语句,直接把某个包下的类直接导入当前类中
Set s;
List l;
//每次使用Arrays类中的静态方法,我们使用了import语句,
//但每次都需要使用arrays类调用静态方法。
}
}
/*
如果A类和B类不在同一个包中,若A类需要使用到B类,
此时就得让A类中取引入B类。
Arrays 类的全限定名是:java.util.Arrays
*/
三、封装思想与访问权限修饰符
1.封装的好处:
1):使调用者正确,方便地使用系统功能,防止调用者随意修改系统属性.
2):提高组件的重用性.
3):达到组件之间的低耦合性(当某一个模块实现发生变化时,只要对外暴露的接口不变,就不会影响到其他模块).
高内聚:把该模块的内部数据,功能细节隐藏在模块内部,不允许外界直接干预。
低耦合:该模块只需要给外界暴露少量功能方法。
class Person
{
String name;
private int age;//只能在本类中访问
void setAge(int a)//专门用于给对象设置age数据,并把传过来数据保存到对象中
{
if(a < 0)
{
System.out.println("NO");
return;
}
age = a;
}
}
class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person();
p.name = "will";
p.setAge(-17);//向外暴露方法的入口
}
}
2.访问权限修饰符
访问权限控制:
private :类访问权限(只能在所在类中访问),
离开本类后不能“直接”访问
不写(缺省):包私有。表示包访问权限,只能在当前类的该包中访问
此刻访问者的包和定义类的包中相同才能访问
如:package a.b包中的只能用a.b的访问,即使是a包也不可以
protected :表示子类访问权限。同包中的可以访问,即使不同包但是有继承关系也可以访问。
public :公共访问权限。若某一字段使用了public修饰。则可以在当前项目中
任何地方访问。
一般的:字段的private修饰,表达隐藏,为了安全性。
拥有实现细节的方法,使用private修饰,不希望外界(调用者)看到方法的实现细节。
一般的方法我们使用public修饰供外界调用。
.
//直接暴露给外界,供调用者直接调用即可
public void doWork()
{
methodA();
methodB();
methodC();
}
//仅仅只是完成了部分操作,不需要调用者调用
private methodA(){}
private methodB(){}
private methodC(){}
一般的:字段都使用private修饰,表达隐藏,为了安全性.
拥有实现细节的方法,一般使用private修饰,不希望外界(调用者)看到该方法的实现细节.
一般的,方法我们使用public修饰,供外界直接调用
一般的,我们不用缺省,即使要使用,也仅仅是暴露给同包中的其他类.
protected:一般,在继承关系中,父类需要把一个方法只暴露给子类.
四、this关键字
什么是this:
表示当前对象,什么优势当前对象.
this主要存在于两个位置:
构造器中: 就表示当前创建的对象.
方法中: 哪一个对象调用this所在的方法,那么此时this就表示哪一个对象.
当一个对象创建之后,JVM会分配一个引用自身的引用:this.
那么先来看一段有问题的代码:
class User
{
private String name = null;
private int age = 0 ;
public void show()
{
System.out.println(this.name + "," + this.age);
}
User()
{
}
User(String name)
{
this(name,0);
}
User(String name,int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int n)
{
age = n;
}
}
class Demo
{
public static void main(String[] args)
{
User u1 = new User("will",17);
u1.show();
User u2 = new User();
u2.setAge(18);
u2.setName("abc");
u2.show();
}
}
使用this:
① 解决成员变量和参数(局部变量)之间的二义性,必须使用;
② 同类中实例方法间互调(此时可以省略this,但是不建议省略)。
③ 将this作为参数传递给另一个方法;
④ 将this作为方法的返回值(链式方法编程);
⑤ 构造器重载的互调,this([参数])必须写在构造方法第一行;
⑥ static不能和this一起使用;
当字节码被加载进JVM,static成员以及存在了.
但是此时对象还没有创建,没有对象,就没有this.
创建对象并给对象设置初始值有两种方式:
方式1:先通过无参数构造器创建出一个对象,再通过对象调用相应的setter方法.
方式2: 直接调用带参数的构造器,创建出来的对象,就有了初始值.
通过构造器和通过setter方法都可以完成相同的功能.
给对象设置数据:
1):setter注入(属性注入).
2):构造注入.
如何选择:
1:如果存在带参数的构造器,方式2是比较简洁的.
2:如果在构建对象的时候需要初始化多个数据,如果使用方式2,那么构造器得提供N个参数,参数过大,不直观,此时方式1,简单明了.
方式1:
User u1 = new User();
u1.setName("Lucy");
u1.setAge(18);
方式2:
User u1 = new User("张三",17);