㈠ java 内部类为什么不能static
java为什么非静态内部类中不能有static修饰的属性,但却可以有常量?
如:
public class InnerClassDemo{
int x;
class A{
static int a = 0;//这样写是不合法的.
static final int b=0;//这样写是合做仿兆法的
}
}
java类加载顺序,首先加载类,执行static变量初始化,接下来执行对象的创建,如果我们要执行代码中的变量大橘int a 初始化,那么必须先执行加载外部类,再加载内部类,最后初始化静态变量 a ,问题就出在加载内部类上面,我们可纯租以把内部类看成外部类的非静态成员,它的初始化必须在外部类对象创建后以后进行,要加载内部类必须在实例化外部类之后完成 ,java虚拟机要求所有的静态变量必须在对象创建之前完成,这样便产生了矛盾。
(有点绕,呵呵)
而java常量放在内存中常量池,它的机制与变量是不同的,编译时,加载常量是不需要加载类的,所以就没有上面那种矛盾。
㈡ java内部类,集合,反射
反射,很有用,在着名的框架中,SSh就大量使用反射机制,例如可以在xml中设置一个分割中文字体的类,在java运行的时候,就可以读取xml知道类的路径,然后使用反射将这个类给加载了,就可以使用这个类啦。
集合的话,相当于数组,但是数组只可以固定大小,集合可以随便大小,是动态的,这样就方便多了。还有的集合提供键-值关系映射,例如Map,很方便。
内部类也很好用,例如你想用一个类,但是这个类又没有必要用作他用,就可以声明内部类,当成一个成员使用啦,这样结构更清晰吧。还有匿名内部类
匿名内部类:
T a=new T(){
public H(){
}
};
例如上面的T是一个接口或抽象类,想要给这个接口或抽象类声明一个实现类,但是这个实现类只用一次就行了,其他的没有用到的,就可以用匿名内部类。不用另外去苦逼的去声明。方便
㈢ 关于Java 匿名内部类的疑问!
1.使用接口创建出来的而非使用类实现接口出来的就是匿名类了。
因为接口是无法new的,而使用接口new对象实际是就是产生了一个没有进行命名的类,而这种类就叫做匿名类了。
interface Abc{
public void fn();
}
class Test{
void fn(){
//这里的new Abc()就是一个匿名类,由接口直接产生,而未通过class XXX implements Abc得到
new Abc(){
public void fn(){}
}
}
}
2.不太清楚你问的东西大概什么意思?说一下我的理敏银笑解搏雹
一个类定义完毕,如果JAVA虚拟机加载了这个类,那么它会将所有的static修饰的成员(变量和方法)加载入栈内存,这一部分内存只有一种时候才会被释放,就是JVM退出的时候。
如果使用该类定义了一个对象,也就是new出来的东西,那么会在堆内存中创建一块内存地址,用于存放这个对象,当该对象被释放掉时(JVM不退出,仅仅是回收了这一块内存),被占用内存将清空。
至于内部类的问题,本人认为内部类实际上就是在一个类中定义了一种新的数据类型,当这种数据类型没有被使用时,JVM不会加载它,换句话说,内部类也是一种类,不使用就不加载,只不过它的格式特殊一些而已,单从JAVA编译后的形态来看,内部类独立成一个.class文件,只不过类名是:外部类名$内部类名.class。所以内部类操作时和普通类是一样的,完全满桥含足普通类的各种加载释放原理。
引用LZ的原话“方法的局部变量位于栈上”这句话我不能苟同,本人认为局部变量是在堆内存中的。
㈣ java 内部类为什么不能用静态方法
静态的对象,在内存中实默认实例派察化尘咐茄的,在加载的时候就会存放到内存中。也就是可以直接调用而不需要手动实例化。理解这个就不难理解楼主说的问题了。首先内部的静态类他是不能直接被实例化的。你必须实例化外部类才能实例简亩化它。而外部类不是默认加载的,他只有在手动实例化之后才有内存分配。这时问题出现了。既然静态对象是默认加载,那么静态内部类应该先于外部类被加载到内存中。那么这是又和我们之前的一个结论相反(首先内部的静态类他是不能直接被实例化的。你必须实例化外部类才能实例化它。)所以这种写法是错误的。
㈤ Java 静态内部类作用
1、变值权限修饰作用,在定义内部类的时候,可以在其前面加上一个权限修饰符static。此时这个内部类就变为了静态内部类。
2、在某些特殊的情况下,少了这个静态内部类还真是不行。如在进行代码程序测试的时候,如果在每一个Java源文件中都设置一个主方法(主方法是某个应用程序的入口,必须具有),那么会出现很多额外的代码。
3、最主要的时这段主程序的代码对于Java文件来说,只是一个形式,其本身并不需要这种主方法。但是少了这个主方法又是万万不行的。在这种情况下,就可以将主方法写入到静态内部类中,从而不用为每个Java源文件都设置一个类似的主方法。
这对于代码测试是非常有用的。在一些中大型的应用程序开发中,则是一个常用的技术手段。
例如:
对于两个类,拥有相同的方法:
class People{
run();
}
interface Machine{
run();
}
此时有一个robot类:
class Robot extends People implement Machine.
此时run()不可直接实现。
interface Machine{
void run();
}
class Person{
void run(){
System.out.println("run");
}
}
class Robot extends Person{
private class MachineHeart implements Machine{
public void run(){
System.out.println("heart run");
}
}
public void run(){
System.out.println("Robot run");
}
Machine.getMachine(){returnnew MachineHeart();
}
class Test{
publicstaticvoid main(String[] args){
Robot robot=new Robot();
Machine m=robot.getMachine();
m.run();
robot.run();
}
}
㈥ Android类加载器以及与Java类加载器区别
加载的字节码不同
相同的是,在程序运行时首先把描述类的数据文件(字节码)加载到内存;
不同的是,Android虚拟机运行的是dex字节码,Java虚拟机运行的class字节码。
(dex字节码:是对class文件优化的产物,不同class文件重复的东西只需保留一份。)
类加载器不同以及类加载器的类体系结构不同
Android类加载器和Java的类加载器的类体系结构不一样:
Android的BootClassLoader和Java的BootStrapClassLoader区别:
Android虚拟机中BootClassLoader是ClassLoader内部类,由java代码实现而不是c++实现,是Android平台上所有ClassLoader的最终parent,这个内部类是包内可见,所以我们没法使用。
Java虚拟机中BootStrapClassLoader是由原生代码(C++)编写的,负责加载java核心类库(例如rt.jar等) .
Android类加载器和Java的类加载器工作机制是类似的,使用双亲委托机制。
㈦ Java:静态内部类调用外部类的方法
static 用在类前面只是表示这个内部类与外面的类之间没有实例之间的兄亏引用关系,是可以在内部类中直接创建外面的类的实例的。编译器不会为我们自动创羡弯神建关联引用,但我们可以创建非关联的实例。
这个时候相当于只是给了特定的可见性控制。
你创建两个内部类,一个 static,一个非 static 然后在 eclipse 的 navigator 视图中打开你的类观察,那个非 static 类,编译器自动创建了一个成员变量用来在外部类和内闹誉部类之间建立关联。
㈧ java中静态内部类什么时候加载
只有在加载内部类的时候才初始化
看懂以下的代码,那么对于类的加载,基本上就没问题了,最后类的加载过程的解释
public class Test6 {
public static void main(String[] args){
new B();
new A.C();
}
}
class A{
private P p1 = new P("A--p1");
static P p3 = new P("A--p3");
public A(){
System.out.println("A()");
}
private P p2 =new P("A--p2");
static{
new P("A--static");
}
{new P("A{...}");}
public static class C {
private P p1 = new P("C--p1");
static P p3 = new P("C--p3");
public C(){
System.out.println("C()");
}
private P p2 =new P("C--p2");
static{
new P("C--static");
}
{new P("C{...}");}
}
}
class B extends A {
private P p1 = new P("B --p1");
static P p3 = new P("B -- p3");
public B() {
System.out.println("B()");
}
public P p2 = new P("B -- p2");
static {
new P("B -- static");
}
{new P("B{...}");}
}
class P {
public P(String s) {
System.out.println(s);
}
}
/*
有父类的情况
1. 加载父类
1.1 为静态属性分配存储空间并赋初始值
1.2 执行静态初始化块和静态初始化语句(从上至下)
2. 加载子类
2.1 为静态属性分配存储空间
2.2 执行静态初始化块和静态初始化语句(从上至下掘森前)
3. 加载父类构造器
3.1 为实例属性分配存数空间并赋初始值
3.2 执判清行实例初始化块和实例初始化语句
3.3 执行构造春滑器内容
4. 加载子类构造器
4.1 为实例属性分配存数空间并赋初始值
4.2 执行实例初始化块和实例初始化语句
4.3 执行构造器内容
5 回到main()
内部类的加载过程也一样
㈨ java类加载器有几种
Java中消拍加载器的种类大致可以分为四种:Bootstrap ClassLoader(由C++语言写成),系统加载器(也就是内部类AppClassLoader),ExtClassLoader,以及java.net.UrlClassLoader.
当我们运行一个程序时,首先是找到JDK安装目下的jvm.dll来启动JAVA虚拟机,而后Bootstrap ClassLoader产生,接下来就是Bootstrap ClassLoader来加载ExtClassLoader,并且指定ExtClassLoader的父加载器为Bootstrap ClassLoader,但是因为Bootstrap ClassLoader用C++语言写的,所以用JAVA的观点来看,这个加载器的实例是不存在的,所以拿腔羡ExtClassLoader的父加载器被设置为了null,然后就是Bootstrap ClassLoader将AppClassLoader装载,并指定其父加载器为ExtClassLoader。
JAVA是按照加载器的圆李委派模型来实现的。这种模型是JAVA安全性机制的保证。并且值得我们注意的就是这几个加载器的默认加载类的路径。对于AppCLassLoder来说,它的路径也就是我们的classpath里面的路径。而对于ExtClassLoader来说,它的路径是jre\lib\ext\classes.对于URLClassLoader来说,它的加载路径是我们指定的url。
㈩ java 中静态内部类字段什么时候初始化
不是的,只有在加载内部类的时候才初始化 //有问题可以继续交神瞎租流x0dx0a楼主只要看懂一下的代码x0dx0a那么对于类的加载x0dx0a基本上就没问神埋题了x0dx0a最后类的加载过程的解释x0dx0apublic class Test6 {x0dx0a public static void main(String[] args){x0dx0a new B();x0dx0a new A.C();x0dx0a }x0dx0a}x0dx0ax0dx0aclass A{x0dx0a private P p1 = new P("A--p1");x0dx0a static P p3 = new P("A--p3");x0dx0a public A(){x0dx0a System.out.println("A()");x0dx0a }x0dx0a private P p2 =new P("A--p2");x0dx0a static{x0dx0a new P("A--static"); x0dx0a }x0dx0a {new P("A{...}");}x0dx0a x0dx0a public static class C {x0dx0a private P p1 = new P("C--p1");x0dx0a static P p3 = new P("C--p3");x0dx0a public C(){x0dx0a System.out.println("C()");x0dx0a }x0dx0a private P p2 =new P("C--p2");x0dx0a static{x0dx0a new P("C--static"); x0dx0a }x0dx0a {new P("C{...}");}x0dx0a }x0dx0a}x0dx0ax0dx0aclass B extends A {x0dx0a private P p1 = new P("B --p1");x0dx0a static P p3 = new P("B -- p3");x0dx0a public B() {x0dx0a System.out.println("B()"); x0dx0a }x0dx0a public P p2 = new P("B -- p2");x0dx0a static {x0dx0a new P("B -- static");x0dx0a }x0dx0a x0dx0a {new P("B{...}");}x0dx0a}x0dx0ax0dx0aclass P {x0dx0a public P(String s) {x0dx0a System.out.println(s);x0dx0a } x0dx0a}x0dx0a/*x0dx0a x0dx0a有父类的情况x0dx0a1. 加载父类x0dx0a 1.1 为静态属性分配存储空间并赋初始值 x0dx0a 1.2 执行静态初始化块和静态初始化语句(从上至下)x0dx0a2. 加载子类x0dx0a 2.1 为静态属性分配存储空间x0dx0a 2.2 执行静态游兆初始化块和静态初始化语句(从上至下)x0dx0a3. 加载父类构造器x0dx0a 3.1 为实例属性分配存数空间并赋初始值 x0dx0a 3.2 执行实例初始化块和实例初始化语句x0dx0a 3.3 执行构造器内容x0dx0a4. 加载子类构造器x0dx0a 4.1 为实例属性分配存数空间并赋初始值 x0dx0a 4.2 执行实例初始化块和实例初始化语句x0dx0a 4.3 执行构造器内容x0dx0a5 回到main()x0dx0a内部类的加载过程也一样x0dx0a*/