深入理解Java中的public、static关键字及其在类关系中的应用
转载自:Java中public和static的理解首先是public

在解释这四个关键字之前,我先对类之间的关系做一个简单的定义。对于继承自己的类,基类可以将它们视为自己的子类,而对于与自身在同一目录中的类,则认为它们都是你的朋友。
1. public:public表示数据成员和成员函数对所有用户开放,所有用户都可以直接调用。
2、Private:私有的意思是私有的。私有意味着除了类本身之外任何人都不能直接使用它。私有财产神圣不可侵犯。即使是孩子和朋友也无法使用它。
3. Protected:Protected对孩子和朋友公开,可以自由使用,没有任何限制。但是,受保护的对象对于其他外部类来说变为私有的。
范围 当前类、同一包的后代、其他包
公共 √ √ √ √
受保护√ √ √ ×
友善 √ √ × ×
私人 √ × × ×
不写时默认为友好
然后就是静电
static在java中是静态的意思
但这个静电是什么意思呢?
刚开始接触static的时候,根本不理解书本上的概念!
我接触Java有一段时间了。这里我总结一下我对static的理解:
(概念)static的意思是“全局”或“静态”,用于修改成员变量和成员方法。也可以组成静态代码块,但是Java语言中没有全局变量的概念。
这句话的意思是你会使用static来修改一些变量、方法、方法块等,这就是你使用static的地方; “但是,Java中没有全局变量的概念。”这句话怎么理解呢?你必须永远记住Java是一种面向对象的语言。一切都是对象。无论做什么,都需要创建一个对象,然后调用这个对象的方法。 Java怎么能允许存在一个全世界通用的“全局变量”呢? “‘’这个概念存在吗?所以Java中根本不存在所谓的“全局变量”,但是没有这个概念并不意味着你不能实现这个功能。 Java存在的目的就是为了让人们用它来达到自己想要的效果,所以静态值可以达到全局变量的作用,所以现在你应该能够理解下面这句话了。
(概念)静态成员变量和用public修饰的成员方法本质上都是全局变量和全局方法。当声明其类的对象时,不会生成静态变量的副本,但该类的所有实例共享相同的静态变量。
现在进一步理解以下两个概念:
(概念)只要加载了这个类,Java虚拟机就可以根据类名在运行时数据区的方法区找到它们。因此,静态对象可以在创建其任何对象之前访问,而无需引用任何对象。
为了根据实际例子来理解这个概念,现在有两个类,Demo1和Demo2。
该实例还包含对静态方法的操作
public class Demo1 {
public static int i = 1;
public int j = 2;
public static int getNumber(){
return i;
// 这个return返回的是全局变量的i,即前面多创建的i
}
public int getDealNumber(int j){
return j;
// 这个return返回的是所传进来的参数,是(int j)这个东西
}
}
public class Demo2 {
public static void main(String args[]){
// 想要得到Demo1中的静态的(即全局的)变量i,直接用类名引用就可以了
int i = Demo1.i;
// 但是想要得到Demo1中的实例的变量j,我需要怎么做呢?(此刻牢记java面向对象的思想!)
// 首先我要先new一个Demo1的对象,然后才可以通过new出来的对象得到Demo1中的j
Demo1 demo1 = new Demo1();
int j = demo1.j;
// 同理,java中的static方法和非static方法都是一样的区别
// 下面一行的方法是静态的,我可以直接根据类名调用方法
int ii = Demo1.getNumber();
// 但是想要调用实例的方法,就需要利用前面所new出来的Demo1的对象来调用了
int jj = demo1.getDealNumber(1);
// 所以现在你可以理解上文紫色的定义了么?
}
}
(概念)静态成员变量和用public修饰的成员方法本质上都是全局变量和全局方法。当声明其类的对象时,不会生成静态变量的副本,但该类的所有实例共享相同的静态变量。
理解了上面的代码之后,这个定义是不是很容易解决呢?这就涉及到堆栈问题。我还没把它们整理好。我会把它们整理出来。写完这篇文章,我马上巩固一下栈的知识。我认为栈的知识非常重要。如果你也是初学者,那就关注我吧。 ,呵呵~
我们先来说说静态变量和实例变量的区别:
两者的区别在于:
对于静态变量,在内存中只有一份(以节省内存)。 JVM 只为静态变量分配一次内存。静态变量的内存分配是在类加载过程中完成的。可以直接通过类名来访问(方便)。当然也可以通过对象来访问。访问(但不建议这样做)。
对于实例变量来说,在创建实例之前,会为实例变量分配一次内存。实例变量在内存中可以有多个副本,互不影响(灵活)。
因此,当需要实现以下两个功能时,一般使用静态变量:
当对象之间共享值时
方便访问变量
现在了解静态方法
2、静态方法
静态方法可以通过类名直接调用,任何实例也可以调用静态方法。前面的代码中有直接通过类名调用的例子。
静态方法中不能使用this和super关键字,也不能直接访问所属类的实例变量和实例方法(即没有static的成员变量和成员方法)。只能访问其所属类的静态成员变量和成员方法。因为实例成员是与特定对象关联的!这就是Java的面向对象思想。实例是类本身的属性。你将使用这个属性来做一些事情,但这些事情不是固定的,不能像静态方法一样是不可变的。设身处地为另一个人着想,一个人是一个Java类,手上是该类的实例方法,而这个人有一部手机,是静态方法。人们只能用手玩手机。你见过有人用手玩手机吗?哈哈
因为静态方法独立于任何实例,所以静态方法必须是实现的,不能是抽象的。静态方法是类中的一种特殊类型的方法。仅在需要时才将相应的方法声明为静态。类中的方法通常是非静态的。
如何理解上面的定义呢?记住了,哈哈
3.静态代码块
静态代码块也称为静态代码块。它是类中独立于类成员的静态语句块。可以有多个并且可以放置在任何地方。它不在任何方法体中。这些静态代码块将在 JVM 加载类时执行。 ,如果有多个静态代码块,JVM会按照它们在类中出现的顺序执行它们,并且每个代码块只会执行一次。例如:
public class Test5 {
private static int a;
private int b;
static{
Test5.a=3;
System.out.println(a);
Test5 t=new Test5();
t.f();
t.b=1000;
System.out.println(t.b);
}
static{
Test5.a=4;
System.out.println(a);
}
public static void main(String[] args) {
// TODO 自动生成方法存根
}
static{
Test5.a=5;
System.out.println(a);
}
public void f(){
System.out.println("hhahhahah");
}
}
运行结果:
哈哈哈哈
1000
可以使用静态代码块给一些静态变量赋值。最后,看一下这些例子。它们都有一个静态的main方法,这样JVM在运行main方法时可以直接调用它,而不需要创建实例。
还需要我再说什么吗?
有时您想要定义一个类成员,以便其使用完全独立于该类的任何对象。通常,类成员必须通过其类的对象来访问,但是可以创建一个可以由其自身使用而无需引用特定实例的成员。这样的成员可以通过在成员声明前添加关键字static(静态)来创建。如果将成员声明为静态,则可以在创建其类的任何对象之前访问它,而无需引用任何对象。您可以将方法和变量声明为静态。静态成员最常见的示例是 main()。由于 main() 必须在程序开始执行时调用,因此将其声明为静态。
如果你看不懂这句话,只要倒过来读,你就会有一个大概的了解。
注意几点
声明为静态的变量本质上是全局变量。当声明一个对象时,不会生成静态变量的副本,但该类的所有实例变量共享同一个静态变量。声明为静态的方法有以下限制:
•
他们只能调用其他静态方法。
•
他们只能访问静态数据。
•
它们不能以任何方式引用 this 或 super(关键字 super 与继承相关,将在下一章中介绍)。
如果需要通过计算初始化静态变量,可以声明静态块。 Static 块仅在类加载时执行一次。
以下示例显示了一个具有静态方法、一些静态变量和静态初始化块的类:
// Demonstrate static variables,methods,and blocks.
class UseStatic {
static int a = 3;
static int b;
static void meth(int x) {
System.out.println("x = " + x);
System.out.println("a = " + a);
System.out.println("b = " + b);
}
static {
System.out.println("Static block initialized.");
b = a * 4;
}
public static void main(String args[]) {
meth(42);
}
}
加载 UseStatic 类后,所有静态语句都会运行。首先,a被设置为3,然后执行静态块(打印一条消息),最后,b被初始化为a*4或12。然后调用main(),main()调用meth(),传递值 42 为 x。三个println()语句引用了两个静态变量a和b,以及局部变量x。
注意:在静态方法中引用任何实例变量是非法的。