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来进行很方便的传参,
主函数里面对参数进行遍历
但是其实不知道这样进行传参的具体意义所在。
自己的理解浅显,希望自己可以不断学习,获得更多更加深入的认识。 希望得到指点。