java基础系列之四:java基本语法

本文深入讲解Java中的包、类、接口、内部类等核心概念,包括它们的定义、使用方法及注意事项,帮助读者全面掌握Java编程的基础知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要内容:
 包
 类的说明符
 方法的说明符
 对象的销毁
 接口
 内部类和匿名内部类
 异常处理

1、包(package)
  为了便于管理大型软件系统中数目众多的类,解决类命名冲突的问题,java引入了包。
  package必须是文件中的第一条语句,也就是说,在package语句之前,除了空白和注释之外不能有其他语句。
  如果不加package语句,则指定为缺省包或无名包。
  包对应着文件系统的目录层次结构。
  在package语句中,用“.”来指明包(目录)的层次。
 
2、编译并生成包
  在当前目录下生成包
  javac -d . Test.java
  在指定目录下生成包
  javac -d E:JavaLesson Test.java
  编译某一目录下所有java文件,此时不用当心编译次序
  javac *.java
  设置了环境变量之后,会默认在环境变量指定的目录下搜索类。
  set classpath=%classpath%;d:java\;
 
3、import语句
  引入包中的类
  import java.io.File;
  引入整个包
  import java.io.*;
  在同一包中的类可以相互引用,无需import语句。
  java.lang包是默认导入的,编写程序时,无需显示导入。
  没有导入相应包时,必须在调用类时写上类的全名。

4、类的说明符
  1>类的访问说明符
  public
  default(不加访问说明符时)
  2>类的其他修饰符
  final
  abstract
 
5、方法的说明符
  1>方法的访问说明符
  public
  protected
  default(不加访问说明符时)
  private
  2>方法的其他修饰符
  static
  final
  abstract
  native
  synchronized
 
6、方法的访问控制
      public protected default private
  同类   yes   yes    yes   yes
  同包   yes   yes    yes
  子类   yes   yes
  通用   yes 

7、final方法
  为了确保某个函数的行为在继承过程中保持不变,并且不能呗覆盖,可以使用final方法。
  为了效率上的考虑,将方法声明为final,让编译器对此方法的调用进行优化。要注意的是:编译器会自动对final方法进行判断,并决定是否进行优化。通常在方法的体积很小,而我们确实不希望它被覆盖时,才将它声明为final。
  class中所有的private和static方法自然就是final。
 
8、抽象方法和抽象类
  在类中没有方法体的方法,就是抽象方法。
  含有抽象方法的类,即位抽象类。
  如果一个子类没有实现抽象基类中所有的抽象方法,则子类也成为一个抽象类。
  抽象类不能实例化。
  我们可以将一个没有任何抽象方法的类声明为abstract,避免有这个类产生任何的对象。
  构造方法,静态方法,私有方法,final方法不能被声明为抽象的方法。
 
9、native方法
  native方法是用户在java中可以使用,但不能编写的方法。
  JNI(Java Native Interface),它允许java虚拟机(JVM)内部运行的java代码能够与其他编程语言(如C,C++,汇编语言)编写的应用程序和库进行互操作。
  JNI最大的好处是它没有对底层java虚拟机的实现施加任何限制,因此,java虚拟机厂商可以在不影响虚拟机其他部分的情况下添加对JNI的支持。程序员只需编写一种版本的本地应用程序和库,就能够与所有支持JNI的java虚拟机协同工作。
  JNI可以理解为java和本地应用程序之间的中介。
  书写步骤:
  ·编写带有native声明的方法的java类   
  ·使用javac命令编译所编写的java类  JNI
  ·使用javah -jni java类名生成扩展名为h的头文件   
  ·使用C/C++实现本地方法   
  ·将C/C++编写的文件生成动态连接库   
  ·使用java命令运行java类
   
10、垃圾回收机制
   垃圾回收是一个低优先级的线程在后台自动运行。
   System.gc()用来显示调用垃圾回收方法finalize()。
 
11、接口
   实现接口采用关键字implements。
   接口中所有方法默认都是public abstract。
   接口中数据成员默认都是public static final。
   在接口中声明方法时,不能使用native、static、final、synchronized、private、protected等修饰符。
   和public类一样,public接口也必须定义在与接口同名的文件中。
   实现一个接口时,如果不能实现其中所有方法,必须将类定义为抽象类。
   一个接口可以继承自另一个或多个接口。
   java中不允许类的多继承,但允许接口的多继承。
   interface Sittable
  {
   void sit();
  }
  interface Lie
  {
   void sleep();
  }
  interface Chair extends Sittable
  {
  }
  interface Sofa extends Sittable, Lie //一个接口继承多个接口
  {
  }
  class Sofa1 implements Sittable, Lie //一个类实现多个接口
  {
   public void sit()
   {
   }
   public void sleep()
   {
   }
  }
  interface HealthCare
  {
   void massage();
  }
  class Chair implements Sittable
  {
   public void sit(){};
  }
  class Sofa extends Chair implements Lie, HealthCare //在继承类的同时,实现多个接口
  {
   public void sleep(){};
   public void massage(){};
  }

12、内部类
  在一个类中定义另外一个类,这个类就叫内部类或内置类。
  内部类可以将逻辑上相关的一组类组织起来,并有外部类来控制内部类的可见性。
  当我们建立一个内部类时,其对象就拥有了与外部类对象之间的一种关系,这是通过一个特殊的this引用形成的,使得内部类对象可以随意访问外部类中所有成员。
  内部类访问外部类时,须使用Outer.this.变量。
  在方法中定义的内部类,如果要访问方法中定义的本地变量或方法的参数,则变量必须声明为final。
  内部类可以声明为private和protected,还可以声明为abstract和final。
  内部类可以声明为static,但此时不能再使用外部类的非static成员变量和非static的成员方法。
  非static的内部类中的成员不能声明为static的,只有在顶层类或static的内部类中才可声明static成员。
  其他类访问某外部类的非静态内部类时,应该使用new Outer().new Inner();
  为什么使用内部类?
  1>在内部类中,可以随意的访问外部类的成员,可以更好的组织管理我们的代码,增强代码的可读性。
  2>内部类可以用于创建适配器类,适配器类是用于实现接口的类,使用内部类来实现接口,可以更好的定位与接口关联的方法在代码中的位置。
  3>内部类的更多用法。
  例子程序:
  class Outer{
   private int index=100;
   void print() {
    Inner i=new Inner();
    i.print();
   }
   void fn(final int a)
   {
    final int b=0;
    if(true)
    {
     class Inner{
      void print(){
       int index=30;
       System.out.println(index); //输出30
       System.out.println(Outer.this.index); //输出100
       System.out.println(a);
       System.out.println(b);
      }
     }
    }
   }
   
  }
  class Test{
   public static void main(String[] args){
    Outer o=new Outer();
    o.print();
    Outer.Inner inner=outer.new Inner();
   }
  }
  
  class Car
  {
   class Wheel
   {
   }
  }
  class PlaneWheel extends Car.Wheel
  {
   PlaneWheel(Car car)
   {
    car.super(); //通过super.car(),建立一个内部类对象到外部类对象的引用关系
   }
   public static void main(String[] args)
   {
    Car car = new Car();
    PlaneWheel pw = new PlaneWheel(car);
   }
  }
  
  interface Animal
  {
   void eat();
   void sleep();
  }
  class Zoo
  {
   private class Tiger implements Animal //私有内部类实现接口,隐藏实现细节
   {
    public void eat()
    {
     System.out.println("tiger eat");
    }
    public void sleep()
    {
     System.out.println("tiger sleep");
    }
    Animal getTiger()
    {
     return new Tiger();
    }
    Animal getAnimal()
    {
     return new Animal() //匿名内部类
     {
      public void eat()
      {
       System.out.println("animal eat");
      }
      public void sleep()
      {
       System.out.println("animal sleep");
      }
     };
    }
   }
  }
  class Test
  {
   public static void main(String[] args)
   {
    Zoo z=new Zoo();
    Animal tiger=z.getTiger();
    tiger.eat(); //输出tiger eat
    tiger.sleep(); //输出tiger sleep
    Animal animal=z.getAnimal();
    animal.eat(); //输出animal eat
    animal.sleep(); //输出animal sleep
   }
  }
  
  内部类解决接口和父类中的相同方法表示的意义不同的问题,解决和C++中多继承相似的问题。
  Machine.java:
  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");
    }
   }
   Machine getMachine()
   {
    return new MachineHeart();
   }
  }
  class Test
  {
   public static void main(String[] args)
   {
    Robot robot=new Robot();
    Machine machine=robot.getMachine();
    machine.run(); //输出heart run
    robot.run(); //输出run
   }
  }
  
  A.java:
  class A
  {
   voidn fn1()
   {
   }
  }
  abstract class B
  {
   abstract void fn2();
  }
  class C extends A
  {
   B getB()
   {
    return new B()
    {
     public void fn2();
    };
   }
  }
  class Test
  {
   static void method1(A a)
   {
    a.fn1();
   }
   static void method2(B b)
   {
    b.fn2();
   }
   public static void main(String[] args)
   {
    C c=new C();
    method1(c);
    method2(c.getB());
   }
  }
  
13、异常类
  1>异常处理
   打开一个不存在的文件、网络连接中断、数组下标越界、正在加载的类文件丢失等都会引发异常。
   java中的异常类定义了程序中遇到的轻微的错误条件。
   java中的错误类定义了程序中不能恢复的严重错误条件。如内存溢出、类文件格式错误等。这一类错误由java运行系统处理,不需要我们去处理。
   java程序在执行过程中如出现异常,会自动生成一个异常类对象,该异常对象将被提交给java运行时系统,这个过程称为抛出(throw)异常。
   当java运行时系统接收到异常对象时,会寻找能处理这一异常的代码并把当前异常对象交给其处理,这一过程称为捕获(catch)异常。
   如果java运行时系统找不到可以捕获异常的方法,则运行时系统将终止,相应的java程序将退出。
   异常处理语句:try/catch/finally语句。
   对于运行时异常(RuntimeException),通常不需要我们去捕获,这类异常由java运行系统自动抛出并自动处理。
   如果父类中的方法抛出多个异常,则子类中的覆盖方法要么抛出相同的异常,要么抛出异常的子类,但不能抛出新的异常(构造方法除外,因为构造方法不能被继承)。
   我们可以在方法声明时,声明一个不会抛出的异常,java编译器就会强迫方法的使用者对异常进行处理。这种方式通常应用于abstract base class和interface中(目前没有异常,以后可能增加代码产生异常)。
  Excep.java:
  class Excep
  {
   Excep() throws ArithmeticException
   {
   }
   public int division1(int a, int b) throws ArithmeticException
   {
    return a/b;
   }
   public int division2(int a, int b) throws Exception
   {
    return a/b;
   }
   catch(ArithmeticException e)
   {
    e.printStackTrace();
    throw new Exception("can't divide by zero");
   }
   public int division3(int a, int b) throws ArithmeticException,DivisorIsMinusException
   {
    if(b<0)
    {
     throw new DivisorIsMinusException("divisor can't be minus");
    }
    return a/b;
   }
   public int fn1(int a, int b) throws Exception // 抛出异常
   {
    return division1(a,b);
   }
  }
  class ChildExcep extends Excep
  {
   ChildExcep throws FileNotFoundException //可以抛出与父类构造方法不同的异常,因为构造方法不被继承
   {
   }
   public int division3(int a, int b) throws ArithmeticException,DivisorIsMinusException //只能抛出与父类方法相同的异常或其子类异常
   {
    return a/b;
   }
  }
  class DivisorIsMinusException extends Exception
  {
   DivisorIsMinusException(String str)
   {
    super(str);
   }
  }
  class ExcepTest
  {
   public static int method1(Excep excep)
   {
    try
    {
     return excep.division3(5,0);
    }
    catch(ArithmeticException e)
    {
     System.out.println(e.toString());
    }
    catch(DivisorIsMinusException ex)
    {
     System.out.println(ex.toString);
    }
    return 0;
   }
   public static void main(String[] main)
   {
    ChildExcep ce=new ChildExcep();
    method1(ce);
    Excep excep=new Excep();
    try
    {
     //excep.division1(5,0); //如果未捕获异常将抛出ArithmeticException,程序终止;如果捕获异常,则跳转到catch语句中继续执行
     excep.fn1(5,0);
     System.out.println("exception"); //此条语句得不到执行
    }
    catch(ArithmeticException e)
    {
     System.out.println("can't divide by zero");
     //System.out.println(e.getMessage()); //输出:/ by zero
     //System.out.println(e.toString()); //输出:java.lang.ArithmeticException:/ by zero,比e.getMessage()详细
     //e.printStackTrace(); //输出:java.lang.ArithmeticException:/ by zero及错误所在位置,如果没有捕获异常,jvm会调用此方法打印错误信息
     //System.exit(-1); //finally中语句不被执行
    }
    catch(Exception e) //所有异常都是Exception派生出来的,所以先捕获特殊异常,再捕获一般异常,以免发生重复捕获错误
    {
     e.printStackTrace();
    }
    finally
    {
     System.out.println("finally"); //任何情况下都会执行,即使try或catch中包含return语句,通常用来关闭数据库连接及释放资源。
    }
    System.out.println("finish");
   }
  }
  输出:
  can't divide by zero
  finally
  finish
  
14、java编程规范
  1>package的命名
   package的名字由全部小写的字母组成,例如:cn.com.mybole。
  2>class和interface的命名 class和interface的名字由大写字母开头而其他字母都小写的单词组成,例如:Person,RuntimeException。
  3>class变量的命名 变量的名字用一个小写字母开头,后面的单词用大写字母开头,例如:index,currentImage。
  4>class方法的命名
    方法的名字用一个小写字母开头,后面的单词用大写字母开头,例如:run(),getBalance()。
  4>static final变量的命名 static final变量的名字所有字母都大写,并且能表示完整含义。例如:PI,PASSWORD。
  5>参数的命名 参数的名字和变量的命名规范一致。
  6>数组的命名 数组应该总是用这样的方式来命名:byte[] buffer。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值