java内部类以及为什么要用public static void修饰main()函数,String args[]是什么?(浅显的一些探索)

2022-07-16 13:07:26 浏览数 (1)

java内部类和外部类,以及main方法的一些探索

  • 内部类
    • 成员内部类
    • 局部内部类
    • 匿名内部类
  • main方法的一些疑问
    • 为什么main方法要用static修饰
    • 为什么需要public 修饰符?
    • 为什么需要void修饰?
    • 为什么main方法里面的参数是(String[] args)(一个字符串数组?)

内部类

成员内部类

成员内部类就是定义在一个类的内部,其实是相当于成员变量的位置。 下面这两种其实都可以被称为成员内部类的,只不过一般static修饰的这种我们一般也可以称之为静态内部类。我们先来研究成员内部类(也可以称之为非静态内部类)怎么定义的话合理即可,明白意思就可以了。

代码语言:javascript复制
class Outer{
	class Inner{
		//非静态成员内部类
    }
    static class Inner_1
    {
		//静态成员内部类
    }
	public static void main(String args[]){
	/*.........*/
	}

}

来看一个简单的例子,也可以自己去测试访问和定义的修饰符

代码语言:javascript复制
package java_practice;

public class OuterandInner {
    private byte b = 1;
    static String country = "china";
    String home = "shanxi";

    public void systemdemo() {
//        System.out.println(Inner.this.name);//这样是不可以的。
    }

    public String author = "jgdabc";

    class Inner {

        String name = "jgdabc";
        //        static String name_1 = "";//这样不允许
        private String password = ".....";

        public void systemdemo() {
            System.out.println(OuterandInner.this.author);
            System.out.println(author);
            System.out.println(Inner_1.age);
//            System.out.println(name_1);//这样访问不了
            System.out.println(b);//非静态内部类可以访问到外部私有化成员
        }
    }

    static class Inner_1 {
        public static void showdemo() {
            //.....
//            System.out.println(Inner.name);//这样不可以
//            Inner inner = new Inner();//不可以这样去new,因为没有main方法
//            System.out.println(b);//静态局部内部类是不能访问到外部类私有成员的
            System.out.println(country);

        }

        String name_1 = "jgdabc_1";
        private String password_1 = "lmddkskk";
        static int age = 19;

        public void systemdemo() {
//            System.out.println(OuterandInner.this.author);//这样是不可以的
            System.out.println(OuterandInner.country);//这样可以访问,并且直接通过类名进行访问

        }

    }

    public static void main(String args[]) {
        System.out.println("......");

        OuterandInner outerandInner = new OuterandInner();
//        System.out.println(outerandInner.name);//访问不到内部类成员
//        System.out.println(name);//
        System.out.println(outerandInner.author);//自己的成员变量直接可以通过实例访问
        Inner inner = outerandInner.new Inner();

        System.out.println(inner.name   inner.password);
//        Inner inner1 = new Inner();//动态的外部类不能被直接在外部类new()
//        System.out.println(name_1);//不能访问
        OuterandInner outerandInner1 = new OuterandInner();
//        System.out.println(outerandInner1.name);//不能访问
        Inner_1 inner_1 = new Inner_1();//静态的可以直接进行new实例化
        System.out.println(inner_1.name_1   inner_1.password_1);
        System.out.println(Inner_1.age);//直接通过类名来调用静态成员内部类的静态成员
//        System.out.println(Inner_1.name);//这样是不可以的
        Inner_1.showdemo();//也可以直接通过类名调用静态成员内部类的静态方法。


    }
}

上面代码测试了一些常规的方法。下面简单说明几点

1:首先非静态成员内部类里面是不可以定义静态的属性的,否则编译不会通过。

2:非静态成员内部类成员不能被外部直接访问,不能只通过实例外部类访问内部类成员

3:访问非静态成员内部类成员属性可以通过外部类实例的对象.new 内部类, 示例如下

代码语言:javascript复制
// An highlighted block
        Inner inner = outerandInner.new Inner();

4:非静态成员内部类可以访问到外部类的属性 然后可以通过inner调用非静态成员内部类属性。

5:非静态成员内部类可以访问到外部私有化属性。


6:外部类也是不能直接访问静态局部成员内部类成员的,这个特点同属于对内部类访问的特点。 7:静态成员内部类可以直接自己进行实例化,而无需通过外部类实例进行调用实例化。 8:静态成员内部类不可以访问到外部类的私有化成员

9:静态成员内部类可以直接访问到外部类的静态成员

10:静态成员内部类不能直接访问外部类非静态成员

局部内部类

局部内部类是一个在方法中定义的内部类 既然是局部内部类,定义在方法体中,那么只在当前方法体当中有效。无论是静态的还是非静态的,都是一样的法则。

特别注意它的作用范围,就是是去实例化它所在的类,只要不再方法体内都是无效。

代码语言:javascript复制
public void systemdemo() {
        class demo_test {
            int age = 19;
            public int id = 123;
//          static String name= "hello";//不可以有静态修饰的成员
//            static void system_demo()
//            {
//                //不可以这样用
//            }
            private String password = "";
            public void show_demo() {
                System.out.println("我是局部内部类");
                   System.out.println(home b password);//可以访问到外部类的成员,即便是私有的。
            }
        }
        demo_test demo_test = new demo_test();
        demo_test.show_demo();
//        System.out.println(Inner.this.name);//这样是不可以的。
    }
//    new demo_test();//这样是不可以的

没有静态局部内部类一说

匿名内部类

匿名内部类也是经常会用到,就比如在重写一个比较器的时候可以通过类名内部类实现。另外,我们也可以自己定义一些具备功能的接口去实现匿名内部类。 简单举例说明一下

代码语言:javascript复制
package java_practice;
class demo{
    public void demo()
    {
        System.out.println("demo");
    }
}

public class AnonymousInner {
    public static void main(String args[])
    {
        new demo(){
            public void demo()
            {
                System.out.println("demo重写");
            }
        }.demo();

    }

}

下面这个例子实现了内名进行重写比较器

代码语言:javascript复制
package java_practice;

import java.util.Comparator;
import java.util.Set;
import java.util.TreeMap;

public class TreeMapDemo01 {
    public static void main(String args[])
    {
        TreeMap tm = new TreeMap<String,String>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //。。。
            }
        });
        tm.put("Hello","world");
        String  set = String.valueOf(tm.keySet());
        System.out.println(set);
        System.out.println(set.getClass());
        System.out.println(set);

    }
}

代码语言:javascript复制
package java_practice;

public class Student implements Comparable<Student>{
    private int age;
    private String name;

    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }





    @Override
    public int compareTo(Student s) {
        int num = this.age - s.age;
        int num2 = num == 0 ? this.name.compareTo(s.name) : num;
        return num2;
    }
}
代码语言:javascript复制
package java_practice;

import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo1 {
    public static void main(String args[]) {
        TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                int num = s1.getAge() - s2.getAge();
                int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
                return num2;
            }
        });

        Student s1 = new Student(29, "西施");
        Student s2 = new Student(28, "王昭君");
        Student s3 = new Student(30, "貂蝉");
        Student s4 = new Student(33, "杨玉环");
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        for (Student s : ts) {
            System.out.println(s.getName()   ""   s.getAge());
        }

    }
}

匿名内部类实现接口

先给一个不适用匿名内部类实现的例子

代码语言:javascript复制
package java_practice;
interface Demo_{
    void demo_d();
}
class Demo_im implements Demo_
{

    @Override
    public void demo_d() {
        System.out.println("实现demo_");
    }
}
public class Demo_de {

    public static void main(String args[])
    {
        Demo_im demo_im = new Demo_im();
        demo_im.demo_d();


    }
}
代码语言:javascript复制
package java_practice;
interface Demo_{
    void demo_d();
}

public class Demo_de {

    public static void main(String args[])
    {
        Demo_ demo= new Demo_(){

            @Override
            public void demo_d() {
                System.out.println("匿名实现接口");
            }
        };
        demo.demo_d();
    }
}

main方法的一些疑问

为什么main方法要用static修饰

我就疑惑为什么mian方法非要是静态的? 我的理解比较浅显。因为这样的设计一定经过很好的预先思考的。对java的底层理解不是很深入。所以自己去参考了一些说法。

首先我们自己从程序执行上面去理解。我们的main方法是在类中,在类中的方法的一个特点就是如果如果不用static修饰,那就必须用实例化才可以访问,但是main是作为程序的如果啊!我们如果不进行直接访问的话,就得自己去实例化main,这样就比较复杂了。所以用static修饰得话,对我们得使用带来了一定得不变。这样其实这样修饰类成为了一种约定。

static修饰方法得特点再说明一下。

也就是说,static 修饰的方法陈为静态方法,静态方法是不依赖类的实列的,不需要通过类的实例去调用。main方法的调用是通过类的加载,链接,以及初始化,main没有被实例化过,所以需要调用的只能是通过声明为静态,然后进行调用。

为什么需要public 修饰符?

这个就比较简单了。我们的java程序需要靠java虚拟机来调用,我们的这种执行调用方式属于外部调用,如果没有public修饰,是无法实现调用的,程序也就无法执行。

为什么需要void修饰?

还是从程序执行需要方面来看,如果没有void修饰是一定需要返回值的。返回值对main又有什么意义呢?我们程序从main函数进行输出就是为了输出程序执行的内容。没有必要去返回值,返回又给谁呢?这不是我们需要的。

对比c,c ,的话,我们就好奇,为什么c,c 就可以进行返回,int main(),执行机制不一样啊,c,c 在程序进入函数执行的是偶,会启动运行时库,然后初始化环境,启动入口函数,然后程序进行执行,执行完毕后,退回运行时库,退回操作系统,然后操作系统继续调度其它的程序。

==但是java就不一样了。我们的java是由jvm进行调度的,jvm调度main函数,jvm被设计为不接受任何返回值,所以也就不能进行返回。 自己的理解浅显,希望自己可以不断学习,获得更多更加深入的认识。

为什么main方法里面的参数是(String[] args)(一个字符串数组?)

String[] args[]或者String args[] 这样都是没有问题的,这个字符串主要的作用就是运行main函数的输入参数,不然它也不会写在那里,我们给main传入参数,args这个数组就会进行接收。

具体是如何传入呢? 可以利用idea来进行很方便的传参,

主函数里面对参数进行遍历

但是其实不知道这样进行传参的具体意义所在。

自己的理解浅显,希望自己可以不断学习,获得更多更加深入的认识。 希望得到指点。

0 人点赞