>  기사  >  Java  >  자바 정적이란 무엇입니까?

자바 정적이란 무엇입니까?

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼원래의
2019-11-14 11:58:104261검색

자바 정적이란 무엇입니까?

1. 정적 메서드

정적 메서드는 일반적으로 정적 메서드라고 합니다. 정적 메서드는 어떤 개체에도 의존하지 않고 액세스할 수 있으므로 정적 메서드에는 첨부되지 않습니다. 어떤 대상도 대상이 없기 때문에 이런 것도 없습니다. 그리고 이 기능으로 인해 클래스의 비정적 멤버 변수와 비정적 멤버 메서드는 정적 메서드에서 액세스할 수 없습니다. 비정적 멤버 메서드/변수는 호출되기 전에 특정 개체에 의존해야 하기 때문입니다.

그러나 비정적 멤버 메서드와 비정적 멤버 변수는 정적 메서드에서 액세스할 수 없지만 정적 멤버 메서드/변수는 비정적 멤버 메서드에서 액세스할 수 있다는 점에 유의해야 합니다. 간단한 예를 들어보겠습니다.

자바 정적이란 무엇입니까?

위 코드에서 print2 메소드는 객체와 독립적으로 존재하므로 클래스 이름을 사용하여 직접 호출할 수 있습니다. 정적 메서드에서 비정적 메서드/변수에 액세스할 수 있는 경우 기본 메서드에 다음 문이 있으면

MyObject.print2();

현재 개체가 없고 str2가 전혀 존재하지 않으므로 모순이 발생합니다. . 메소드의 경우에도 마찬가지입니다. print1 메소드에서는 비정적 멤버 변수에 액세스할지 여부를 예측할 수 없으므로 정적 멤버 메소드에서 비정적 멤버 메소드에 액세스하는 것도 금지됩니다.

비정적 멤버 메서드의 경우 정적 멤버 메서드/변수에 액세스하는 데 분명히 제한이 없습니다.

그래서 객체를 생성하지 않고 메서드를 호출하려면 이 메서드를 static으로 설정하면 됩니다. 가장 일반적인 정적 메서드는 기본 메서드입니다. 기본 메서드가 정적이어야 하는 이유는 이제 명확해졌습니다. 프로그램은 메인 메소드를 실행할 때 어떤 객체도 생성하지 않기 때문에 클래스 이름을 통해서만 접근할 수 있습니다.

또한 생성자가 정적 메서드인지 여부에 대해서는 다음을 참조하세요. http://blog.csdn.net/qq_17864929/article/details/48006835

2. 정적 변수

정적 변수 정적 변수라고도 하며 정적 변수와 비정적 변수의 차이점은 정적 변수는 모든 개체에서 공유되며 메모리에 복사본이 하나만 있고 [메서드 영역에 저장됨] 때 초기화됩니다. 클래스가 처음 로드될 때만 [final이 있는 정적 변수와 final이 없는 정적 변수의 초기화 위치가 다릅니다]. 비정적 변수는 객체가 소유하며 객체가 생성될 때 초기화됩니다. 복사본이 여러 개 있으며, 각 객체가 소유한 복사본은 서로 영향을 미치지 않습니다.

정적 멤버 변수의 초기화 순서는 정의된 순서대로 초기화됩니다.

3. 정적 코드 블록

정적 키워드는 프로그램 성능을 최적화하기 위해 정적 코드 블록을 구성하는 데에도 중요한 역할을 합니다. 정적 블록은 클래스의 어느 위치에나 배치될 수 있으며, 클래스에는 여러 정적 블록이 있을 수 있습니다. 클래스가 처음 로드되면 각 정적 블록은 정적 블록 순서대로 실행되며 한 번만 실행됩니다. [클래스 로딩 원칙에 따라 각 클래스는 상위 위임 로딩을 사용하여 한 번 로드됩니다.]

초기화 순서 정적 코드 블록 > 생성자 코드 블록 > 생성자

public class Client {
{//构造代码块
System.out.println("执行构造代码块");
}
}

정적 블록을 사용하여 프로그램 성능을 최적화할 수 있는 이유는 클래스가 로드될 때 한 번만 실행된다는 특성 때문입니다. 예를 살펴보겠습니다.

class Person{
private Date birthDate;
public Person(Date birthDate) {
this.birthDate = birthDate;
}
boolean isBornBoomer() {
Date startDate = Date.valueOf("1946");
Date endDate = Date.valueOf("1964");
return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
}
}

isBornBoomer는 해당 사람이 1946년에서 1964년 사이에 태어났는지 확인하는 데 사용됩니다. isBornBoomer가 호출될 때마다 startDate와 birthdayDate라는 두 개의 개체가 생성되므로 공간이 낭비됩니다. 실제로는 정적 코드 블록을 메모리에 한 번 로드하는 메커니즘을 사용합니다.

class Person{
private Date birthDate;
private static Date startDate,endDate;
static{
startDate = Date.valueOf("1946");
endDate = Date.valueOf("1964");
}
public Person(Date birthDate) {
this.birthDate = birthDate;
}
boolean isBornBoomer() {
return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
}
}

따라서 한 번만 수행하면 되는 많은 초기화 작업이 정적 코드 블록에서 수행됩니다. .

4. 정적 내부 클래스

여기에서는 정적 내부 클래스를 별도로 작성하지 않습니다. 일반 내부 클래스와 비교하면 정적 내부 클래스에 대한 이해가 깊어질 수 있습니다.

내부 클래스를 사용하는 이유는 무엇인가요?

1. 내부 클래스는 일반적으로 외부 클래스에서만 사용됩니다. [해시맵 컬렉션에 내부 클래스 항목이 있으며 이를 사용하기 위해 변환합니다.]

2. 내부 클래스는 일종의 외부 클래스 창에 들어가면 내부 클래스가 외부 클래스에 대한 참조를 가지므로 내부 클래스가 외부 클래스의 속성에 직접 액세스할 수 있습니다.

3. 매력적인 이유는 외부 클래스가 인터페이스를 상속했는지 여부에 관계없이 각 내부 클래스가 독립적으로 인터페이스를 상속할 수 있기 때문입니다. 따라서 내부 클래스는 다중 상속 솔루션을 더욱 완벽하게 만듭니다.

클래스 내부에 정의된 클래스를 내부 클래스라고 하고, 내부 클래스를 포함하는 클래스를 외부 클래스라고 합니다. 내부 클래스는 public, protected, private 등과 같은 액세스 제한을 선언할 수 있고, 다른 내부 클래스나 외부 클래스가 상속 및 확장할 수 있도록 abstract로 선언할 수 있으며, static 또는 final로 선언하거나 특정 인터페이스를 구현할 수 있습니다.

外部类按常规的类访问方式(以对象的方式)使用内部 类,唯一的差别是外部类可以访问内部类的所有方法与属性,包括私有方法与属性,外部类访问内部类,需要创建对象访问;有一点需要注意,内部类不能访问外部类所在的局部变量,只能访问final修饰的局部变量。

在方法内定义内部类时,如果内部类调用了方法中的变量,那么该变量必须申明为final类型,百思不得其解,后来想到应该是生命周期的原因,因为方法内定义的变量是局部变量,离开该方法,变量就失去了作用,也就会自动被消除,而内部类却不会离开它所在方法就失去作用,它有更广的生命周期。

(1)创建实例

OutClass.InnerClass obj = outClassInstance.new InnerClass(); //注意是外部类实例.new,内部类
AAA.StaticInner in = new AAA.StaticInner();//注意是外部类本身,静态内部类

(2)内部类中的this

内部类中的this与其他类一样是指的本身。创建内部类对象时,它会与创造它的外围对象有了某种联系,于是能访问外围类的所有成员,不需任何特殊条件,可理解为内部类链接到外部类。 用外部类创建内部类对象时,此内部类对象会秘密的捕获一个指向外部类的引用,于是,可以通过这个引用来访问外围类的成员。

(3)外部类访问内部类

内部类类似外部类的属性,因此访问内部类对象时总是需要一个创建好的外部类对象。外部类对象通过‘外部类名.this.xxx’的形式访问内部类的属性与方法。如:

System.out.println("Print in inner Outer.index=" + pouter.this.index);
System.out.println("Print in inner Inner.index=" + this.index);

(4)内部类向上转型

内部类也可以和普通类一样拥有向上转型的特性。将内部类向上转型为基类型,尤其是接口时,内部类就有了用武之地。如果内部类是private的,只可以被它的外部类问,从而完全隐藏实现的细节。

(5)方法内的类

方法内创建的类(注意方法中也能定义类),不能加访问修饰符。另外,方法内部的类也不是在调用方法时才会创建的,它们一样也被事先编译了。

(6)静态内部类

定义静态内部类:在定义内部类的时候,可以在其前面加上一个权限修饰符static。此时这个内部类就变为了静态内部类。

通常称为嵌套类,当内部类是static时,意味着:

[1]要创建嵌套类的对象,并不需要其外围类的对象;

[2]不能从嵌套类的对象中访问非静态的外围类对象(不能够从静态内部类的对象中访问外部类的非静态成员);

嵌 套类与普通的内部类还有一个区别:普通内部类的字段与方法,只能放在类的外部层次上,所以普通的内部类不能有static数据和static字段, 也不能包含嵌套类。但是在嵌套类里可以包含所有这些东西。也就是说,在非静态内部类中不可以声明静态成员,只有将某个内部类修饰为静态类,然后才能够在这 个类中定义静态的成员变量与成员方法。

另外,在创建静态内部类时不需要将静态内部类的实例绑定在外部类的实例上。普通非静态内部类的 对象是依附在外部类对象之中的,要在一个外部类中定义一个静态的内部类,不需要利用关键字new来创建内部类的实例。静态类和方法只属于类本身,并不属于 该类的对象,更不属于其他外部类的对象。

(7)内部类标识符

每个类会产生一个.class文件,文件名即为类名。同样,内部类也会产生这么一个.class文件,但是它的名称却不是内部类的类名,而是有着严格的限制:外围类的名字,加上$,再加上内部类名字。

代码具体:

public class OutClassTest 
{
static int a;
int b;
public static void test() {
System.out.println("outer class static function");
}
public static void main(String[] args) {
// new一个外部类
OutClassTest oc1 = new OutClassTest();
// 通过外部类的对象new一个非静态的内部类
OutClassTest.InnerClass no_static_inner = oc1.new InnerClass();
// 调用非静态内部类的方法
System.out.println(no_static_inner.getKey());
// 调用静态内部类的静态变量
System.out.println(OutClassTest.InnerStaticClass.static_value);
// 不依赖于外部类实例,直接实例化内部静态类
OutClassTest.InnerStaticClass inner = new OutClassTest.InnerStaticClass();
// 调用静态内部类的非静态方法
System.out.println(inner.getValue());
// 调用内部静态类的静态方法
System.out.println(OutClassTest.InnerStaticClass.getMessage());
}
private class InnerClass {
// 只有在静态内部类中才能够声明或定义静态成员
// private static String tt = "0";
private int flag = 0;
public InnerClass() {
// 三.非静态内部类的非静态成员可以访问外部类的非静态变量和静态变量
System.out.println("InnerClass create a:" + a);
System.out.println("InnerClass create b:" + b);
System.out.println("InnerClass create flag:" + flag);
//
System.out.println("InnerClass call outer static function");
// 调用外部类的静态方法
test();
}
public  String getKey() {
return "no-static-inner";
}
}
private static class InnerStaticClass {
// 静态内部类可以有静态成员,而非静态内部类则不能有静态成员。
private static String static_value = "0";
private int flag = 0;
public InnerStaticClass() {
System.out.println("InnerClass create a:" + a);
            // 静态内部类不能够访问外部类的非静态成员
            // System.out.println("InnerClass create b:" + b);
            System.out.println("InnerStaticClass flag is " + flag);
            System.out.println("InnerStaticClass tt is " + static_value);
        }
        public int getValue() {
            // 静态内部类访问外部类的静态方法
            test();
            return 1;
        }
        public static String getMessage() {
            return "static-inner";
        }
    }
    public OutClassTest() {
        // new一个非静态的内部类
        InnerClass ic = new InnerClass();
        System.out.println("OuterClass create");
    }
}

有就是类名ClassName后面多了个.* ,意思是导入这个类里的静态方法。当然,也可以只导入某个静态方法,只要把 .* 换成静态方法名就行了。然后在这个类中,就可以直接用方法名调用静态方法,而不必用ClassName.方法名 的方式来调用。

好处:这种方法的好处就是可以简化一些操作,例如打印操作System.out.println(…);就可以将其写入一个静态方法print(…),在使用时直接print(…)就可以了。但是这种方法建议在有很多重复调用的时候使用,如果仅有一到两次调用,不如直接写来的方便

example:

在Java 5中,import语句得到了增强,以便提供甚至更加强大的减少击键次数功能,虽然一些人争议说这是以可读性为代价的。这种新的特性成为静态导入。当你想使用static成员时,可以使用静态导入(在API中的类和你自己的类上,都可以使用该特性)。下面是静态导入前后的代码实例:

在静态导入之前:

public class TestStatic {
public static void main(String[] args) {
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.toHexString(42));
}
}

在静态导入之后:

import static java.lang.System.out;
import static java.lang.Integer.*;
public class TestStaticImport {
public static void main(String[] args) {
out.println(MAX_VALUE);
out.println(toHexString(42));
}
}

让我们看一下使用静态导入特性的代码中将发生什么:

1 이 기능을 "정적 가져오기"라고 부르기도 하지만 구문은 import static이어야 하며 그 뒤에 가져오려는 정적 멤버의 정규화된 이름이나 와일드카드 문자가 와야 합니다. 이 예에서는 System 클래스의 out 개체에 대해 정적 가져오기를 수행합니다.

2. 이 예에서는 java.lang.Integer 클래스의 여러 정적 멤버를 사용할 수 있습니다. 이 정적 import 문은 와일드카드를 사용하여 "이 클래스의 모든 정적 멤버에 대해 정적 가져오기를 수행하고 싶습니다"라고 말합니다.

3. 이제 드디어 정적 가져오기 기능의 이점을 확인했습니다! System.out.println에 System을 입력할 필요는 없습니다. 매우 좋은! 또한 Integer.MAX_VALUE에 Integer를 입력할 필요가 없습니다. 따라서 이 코드 줄에서는 정적 메서드와 상수에 대한 바로가기를 사용할 수 있습니다.

4. 마지막으로 이번에는 Integer 클래스의 메서드에 대해 더 많은 단축 작업을 수행합니다.

우리는 이 기능에 대해 약간 냉소적이었지만, 우리는 혼자가 아닙니다. 몇 번의 키 입력을 저장한다고 해서 코드를 읽기가 더 어려워지는 것은 아니지만 많은 개발자가 이를 언어에 추가해 달라고 요청했습니다.

정적 가져오기 사용에 대한 몇 가지 원칙은 다음과 같습니다.

정적 가져오기가 아니라 정적 가져오기라고 말해야 합니다.

모호하게 이름이 지정된 정적 멤버에 주의하세요. 예를 들어 Integer 클래스와 Long 클래스에 대해 정적 가져오기를 수행하는 경우 Integer와 Long 모두 MAX_VALUE 상수가 있고 Java는 사용자가 참조하는 MAX_VALUE를 알 수 없기 때문에 MAX_VALUE를 참조하면 컴파일러 오류가 발생합니다.

정적 개체 참조, 상수(정적 또는 최종임을 기억하세요) 및 정적 메서드에 대해 정적 가져오기를 수행할 수 있습니다.

Many java 교육 동영상, 모두 PHP 중국어 웹사이트에 있습니다. 온라인 학습에 오신 것을 환영합니다!

위 내용은 자바 정적이란 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.