Java拾贝不建议作为0基础学习,都是本人想到什么写什么
在Java中主要存在4块内存区域。
栈内存空间:保存所有变量(更准确的说是保存了指向堆内存空间的地址)
堆内存空间:保存每个对象的具体属性内容
全局数据区:保存static类型的属性
全局代码区:保存所有方法定义
static关键字
一个类实例化时会开辟栈内存、堆内存。
栈内存中存放其变量,堆内存中存放对象的属性。每个对象都有自己的属性。
静态属性
如果现在有某属性希望被所有对象共享,那么可以称其为静态(static)属性。也叫全局属性
为举栗子不封装。
public class test5 {
public static void main(String args[]) {
Work work1 = new Work("A",22,"SY");
Work work2 = new Work("B",26,"SY");
work1.Info();
work2.Info();
}
}
class Work {
String name;
int age;
String cityName;
public Work(String name, int age, String cityName) {
this.name = name;
this.age = age;
this.cityName = cityName;
}
public void Info(){
System.out.println(this.name+this.age+this.cityName);
}
}
现有两名SY城的工作者想一起跳槽去TT城,该如何执行代码
public static void main(String args[]) {
Work work1 = new Work("A",22,"SY");
Work work2 = new Work("B",26,"SY");
work1.Info();
work2.Info();
work1.setCityName("TT");
work2.setCityName("TT");
System.out.println("跳槽后");
work1.Info();
work2.Info();
}
/*
A22SY
B26SY
跳槽后
A22TT
B26TT
*/
可以看到确实成功抵达TT城,但如果不止AB两个实例呢?
这时可以使用static,使其被所有对象共享,达成一改全改。
public class test5 {
public static void main(String args[]) {
Work work1 = new Work("A", 22);
Work work2 = new Work("B", 26);
work1.Info();
work2.Info();
Work.cityName="TT";
System.out.println("跳槽后");
work1.Info();
work2.Info();
}
}
class Work {
String name;
int age;
static String cityName="SY";
public Work(String name, int age) {
this.name = name;
this.age = age;
}
public void Info() {
System.out.println(this.name + this.age + this.cityName);
}
}
/*
A22SY
B26SY
跳槽后
A22TT
B26TT
*/
因为cityName被static修饰后被类所拥有,不再局限于某个实例。
可以由类直接调用
//类名.静态属性
Work.cityName="TT";
静态方法
相应的,有静态属性就有静态方法。也叫类方法
静态方法和静态属性相同可以由类直接调用。
类名.方法();
继续使用上述的栗子,但把属性进行封装。
public class test5 {
public static void main(String args[]) {
Work work1 = new Work("A", 22);
Work work2 = new Work("B", 26);
Work.cityName = "TT";//报错,封装后不能直接访问属性
System.out.println("跳槽后");
work1.Info();
work2.Info();
}
}
class Work {
private String name;
private int age;
private static String cityName="SY";
public Work(String name, int age) {
this.name = name;
this.age = age;
}
public void Info() {
System.out.println(this.name + this.age + this.cityName);
}
public static String getCityName() {
return cityName;
}
public static void setCityName(String cityName) {
Work.cityName = cityName;
}
//其他getter和setter
}
修改代码:
Work.cityName = "TT";
?
Work.setCityName("TT");
public static void main(String args[]) {
Work work1 = new Work("A", 22);
Work work2 = new Work("B", 26);
Work.cityName = "TT";//报错,封装后不能直接访问属性
System.out.println("跳槽后");
work1.Info();
work2.Info();
}
/*
跳槽后
A22TT
B26TT
*/
但getter和setter方法为什么也要用static修饰呢?
至此提出静态方法遵循的规则:
- 非static方法可以去调用static属性或方法
- static方法不能调用非static属性或方法
非static方法可以去调用static属性或方法
public class test5 {
public static void main(String args[]) {
Work w = new Work();
w.say();
}
}
class Work {
private String name;
private static String cityName = "SY";
public Work() {
}
public Work(String name) {
this.name = name;
}
public void say() {
tell();
cityName="TT";
System.out.println(Work.cityName);
System.out.println("这是普通方法say");
}
public static void tell() {
System.out.println("这是静态方法tell");
}
/*
这是静态方法tell
TT
这是普通方法say
*/
static方法不能调用非static属性或方法
还是上述的栗子,修改一下tell方法
class Work {
private String name;
private static String cityName = "SY";
public Work() {
}
public Work(String name) {
this.name = name;
}
public void say() {
System.out.println("这是普通方法say");
}
public static void tell() {
System.out.println("这是静态方法tell");
this.say();
this.name="TT";
}
}
//直接编译错误了,连运行都不能运行
其实也不难理解:
因为普通的属性和方法需要对象开辟堆内存空间之后才可以使用。
而static类型的方法不存放于堆内存中,它在内存中有独立的空间。
假设堆内存都还没有开辟完,静态方法怎么找到这个方法去调用呢?
通过实例也可也访问静态方法或静态变量,但编译器会运行过程中自动修改为类名。
接口的静态属性
在接口提到过,接口是不允许存在属性的。
但可以存在静态属性,并且静态属性必须为final。
interface Sex{
public static final int Men=1;
public static final int WoMen=2;
}
就像方法一样,接口中的方法默认为public abstract。
属性默认为public static final。
至此:
interface Sex{
int Men=1;
int WoMen=2;
}
代码块
所谓代码块指的是{}包括的内容,根据位置及关键字不同可以分为
- 普通代码块
- 构造代码块
- 静态代码块
- 同步代码块
普通代码块
普通代码块就是直接在方法中或语句中定义的代码块。
public class test5 {
public static void main(String args[]) {
{//直接定义在方法中的代码块,main方法当然也是方法
int i = 1;//局部变量
System.out.println("普通代码块:"+i);
}
int i = 2;
System.out.println("代码块之外:"+i);
}
}
/*
普通代码块:1
代码块之外:2
*/
构造代码块
构造代码块就是直接写在类中的代码块。
public class test5 {
public static void main(String args[]) {
new T5();
new T5();
new T5();
}
}
class T5 {
{
//初始化本类时会调用构造代码块
System.out.println("构造代码块被调用");
}
public T5() {
System.out.println("构造方法被调用");
}
}
/*
构造代码块被调用
构造方法被调用
构造代码块被调用
构造方法被调用
构造代码块被调用
构造方法被调用
*/
构造代码块优先于构造方法,并且每次实例化对象都会执行构造代码块,会执行多次。
静态代码块
静态代码块就是使用static修饰的代码块
public class test5 {
public static void main(String args[]) {
new T5();
new T5();
new T5();
}
}
class T5 {
static {//静态代码块
System.out.println("静态代码块被调用");
}
{//构造代码块
System.out.println("构造代码块被调用");
}
public T5() {
System.out.println("构造方法被调用");
}
}
/*
静态代码块被调用
构造代码块被调用
构造方法被调用
构造代码块被调用
构造方法被调用
构造代码块被调用
构造方法被调用
*/
静态代码块优先与构造代码块,并且只会执行一次。
同步代码块
多线程内容。
代码块执行顺序
同步代码块不在内
public class test5 {
public static void main(String args[]) {
new T5();
}
}
class T5 {
static {//静态代码块
System.out.println("静态代码块被调用");
}
{//构造代码块
System.out.println("构造代码块被调用");
}
public T5() {
{//普通代码块
System.out.println("普通代码块被调用");
}
System.out.println("构造方法被调用");
}
}
/*
静态代码块被调用
构造代码块被调用
普通代码块被调用
构造方法被调用
*/
至此,代码块优先级如下:
- 静态代码块
- 构造代码块
- 普通代码块