Java基础

Java开发环境

  • Java是一门跨平台语言,它编写的软件可以运行在各种系统上(c++则不然),跨平台特性实现的核心是JVM(Java Virtual Machine,Java虚拟机)
  • JVM是运行所有java程序的假象计算机,是java程序的运行环境,用Java编写的程序都运行在JVM之上
  • JVM本身不具备跨平台功能,每个操作系统下都有不同版本的JVM,JVM可以简单理解为就是实现翻译功能
  • JRE(Java Runtime Environment):是Java程序的运行时环境,包括JVM和运行时需要的核心类库
  • JDK(Java Development Kit):是JAVA程序开发工具包,包含JRE和开发人员使用的工具
    • 想要运行一个Java程序,只需安装JRE
    • 而想要开发一个全新的Java程序,那么需要安装JDK
      在这里插入图片描述

基本数据类型

  • 包含8种基本数据类型,其中包含4种整型int(4字节), short(2字节), long(8字节), byte(1字节),2种浮点类型float(4字节), double(8字节),一种字符类型char(1字节)表示Unicode编码的代码单元和一种用于表示真假的boolean类型
  • Java还有一个能够表示任意精度的算术包,通常成为“大数”(big number),当他并不是一种基本Java类型,而是一个Java对象
  • Java所有数值类型所占据的字节数和范围与运行Java的机器无关,这与C/C++不同,C/C++中,int,long等类型的大小与目标平台相关
  • Java没有任何无符号(unsigned)类型

Java包(package)基础概念

包的作用

  • 1、把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用
  • 2、如同文件夹一样,包也采用了树形目录的存储方式同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突
  • 3、包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类
  • Java 使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)等

包的语法

package pkg1[.pkg2[.pkg3…]];

例如,一个Something.java 文件它的内容

package net.java.util;
  • 那么它的路径应该是 net/java/util/Something.java这样保存的。 package(包) 的作用是把不同的 java 程序分类保存,更方便的被其他 java 程序调用
  • 一个包(package)可以定义为一组相互联系的类型(类、接口、枚举和注释),为这些类型提供访问保护和命名空间管理的功能。
  • 以下是一些 Java 中的包:
    • java.lang-打包基础的类
    • java.io-包含输入输出功能的函数
  • 开发者可以自己把一组类和接口等打包,并定义自己的包。而且在实际开发中这样做是值得提倡的,当你自己完成类的实现之后,将相关的类分组,可以让其他的编程者更容易地确定哪些类、接口、枚举和注释等是相关的
  • 由于包创建了新的命名空间(namespace),所以不会跟其他包中的任何名字产生命名冲突。使用包这种机制,更容易实现访问控制,并且让定位相关类更加简单

包的创建

  • 创建包的时候,你需要为这个包取一个合适的名字。之后,如果其他的一个源文件包含了这个包提供的类、接口、枚举或者注释类型的时候,都必须将这个包的声明放在这个源文件的开头
  • 包声明应该在源文件的第一行,每个源文件只能有一个包声明,这个文件中的每个类型都应用于它
  • 如果一个源文件中没有使用包声明,那么其中的类,函数,枚举,注释等将被放在一个无名的包(unnamed package)中
  • 例子
    • 创建一个包含接口Animal的包
    // file: Animal.java
    package animals;	// 声明包,表示此文件数据animals包
    interface Animal{
    	public void eat(){}
    	public void travel(){}
    }
    
    • 在同一个包中加入该接口的实现
    package animals;	// 声明包,表示此文件数据animals包
    
    /* file : MammalInt.java */
    public class MammalInt implements Animal{
     
       public void eat(){
          System.out.println("Mammal eats");
       }
     
       public void travel(){
          System.out.println("Mammal travels");
       } 
     
       public int noOfLegs(){
          return 0;
       }
     
       public static void main(String args[]){
          MammalInt m = new MammalInt();
          m.eat();
          m.travel();
       }
    }
    

使用包

  • 为了能够使用某一个包的成员,我们需要在 Java 程序中明确导入该包。使用 “import” 语句可完成此功能
  • 在 java 源文件中 import 语句应位于 package 语句之后,所有类的定义之前,可以没有,也可以有多条,其语法格式为:
    import package1[.package2…].(classname|*);
    
  • 在某个类使用同一个包中的类,不需要import
  • 在某个类中引用另一个包的类,需要import
    • import 关键字引入,使用通配符 “*”,引用包中所有类
      import packageName.*;
      
    • 使用 import 关键字引入某个类:
      import packageName.className;
      

Java与C++不同点

  • Java为解释性语言,其运行过程为:程序源代码经过Java编译器编译成字节码,然后由JVM解释执行。而C/C++为编译型语言,源代码经过编译和链接后生成可执行的二进制代码,可直接执行。因此Java的执行速度比C/C++慢,但Java能够跨平台执行,C/C++不能
  • Java是完全面向对象语言,所有代码(包括函数、变量)必须在类中实现,除基本数据类型(包括int、float等)外,所有类型都是类。此外,Java语言中不存在全局变量或者全局函数,而C++兼具面向过程和面向对象编程的特点,可以定义全局变量和全局函数
  • Java的所有代码都必须包含在类中
  • Java 中,只有类定义,没有类声明,且结尾不需要分号
  • Java中没有作用域范围运算符“::”,Java用包代替了C++的命名空间
  • Java的定义类时必须在类名前加上访问修饰符
  • Java的所有方法和字段的声明都必须在前面加上访问修饰符
  • Java的main函数必须用public修饰且是static的
  • Java具有平台无关性,即对每种数据类型都分配固定长度的空间,例如int型总是占据32位;而C/C++不然,同一个数据类型在不同平台上会分配不同的字节数
  • C/C++中,结构和联合的所有成员均为公有,这往往会导致安全性问题的发生;而Java根本就不包含结构和联合,所有内容都封装在类里面
  • C++语言支持预处理;Java没有预处理器,虽然不支持与处理功能(包括头文件、宏定义等),但它提供的import机制与C++的预处理器功能类似
  • C++支持默认函数参数;Java不支持默认函数参数
  • C/C++支持goto语句;Java不提供goto语句,但Java中的goto是保留关键字
  • C/C++支持自动强制类型转换,这会导致程序的不安全;Java不支持自动强制类型转换,必须由开发人员显式地进行强制类型转换
  • Java丢弃了C++ 中很少使用的、很难理解的、令人迷惑的那些特性,如操作符重载、多继承、自动的强制类型转换
  • Java语言不使用指针,并提供了自动的废料收集,在Java语言中,内存的分配和回收都是自动进行的,程序员无须考虑内存碎片的问题
  • Java用接口(Interface)技术取代C++程序中的多继承性。接口与多继承有同样的功能,但是省却了多继承在实现和维护上的复杂性
  • Java有反射机制,允许程序在运行时进行自我检查,同时也允许对其内部的成员进行操作。C++没有提供这样的特性

Java数组初始化方式

  • 动态初始化
    int [] array = new int[10];
    
  • 静态初始化
    int [] array = new int[]{1,2,3,4,5};
    // 静态初始化的省略格式
    int [] array = {1,2,3,4,5};
    
  • 动态和静态初始化分两步走
    // 动态两步
    int [] arrayA;
    arrayA = new int [10];
    // 静态两步
    int [] arrayB;
    arrayB = new int [] {1,2,3,4,5};
    // error, 省略格式不能分两步
    /*
    int [] arrayC;
    arrayC = {1,2,3,4,5};
    */
    
  • 获取数组长度
    //格式:arrayname.length
    int [] array = new int [10];
    int len = array.length;  // 10
    
  • Java使用动态初始化数组时,数组中的元素都会自动拥有一个默认值
    • 若为int类型,默认值为0
    • 若为浮点类型,默认值为0.0
    • 若为字符类型,默认值为/u0000
    • 若为布尔类型,默认值为false
    • 若为引用类型,默认值为null
  • Java数组特性
    • 由于数组类型是Java中的引用类型,所以与c++不同。c++中,数组名是一个指针常量,是不可赋值的。而Java中数组名是一个引用,是指向内存中的地址,可以将数组名引用另一块地址。
    int [] array = new int [10];
    array = new int [5];   // 引用另一块地址
    

Java引用类型

  • 引用类型是一个对象类型,它的值是指向内存空间的引用,就是地址,所指向的内存中保存着变量所表示的一个值或一组值(数组)
  • Java 提供两种不同的类型:引用类型和基本类型(或内置类型),简单地说除了8中基本数据类型,其他都是引用类型
  • 引用类型和基本类型的行为完全不同,并且它们具有不同的语义
    • 引用类型和原始类型具有不同的特征和用法,它们包括:大小和速度问题,这种类型以哪种类型的数据结构存储,当引用类型和原始类型用作某个类的实例数据时所指定的缺省值
    • 对象引用实例变量的缺省值为 null,而基本类型实例变量的缺省值与它们的类型有关。同时为了面向对象操作的一致性
    • 这些基本类型都有相应的封装引用类型:Integer、Short、Long、Byte、Float、Double、Boolean、Character等
  • Java有4种引用类型:分别为强引用(StrongReference),软引用(SoftReference),弱引用(WeakReference)以及虚引用(PhantomReference),他们被GC回收的可能性从大到小排列

匿名对象

  • 由于Java具有自动的内存回收机制,所以对于只使用一次的对象,一般创建一个匿名对象然后调用该匿名对象的方法实现某些功能
  • 也可以使用匿名对象来作为参数进行函数传参和作为函数的返回值
  • 匿名对象只能使用一次
    new ClassName().CallMethod();  // 调用一次匿名对象的方法
    CallMethod(new ClassName());  // 匿名对象传参
    return new ClassName(); 	// 匿名作为返回值
    
  • C++中使用new创建的动态对象需要手动delete释放,所以不可使用匿名对象,否则造成内存泄漏

Java访问修饰符

  • private

    • 1.在当前类开发中,main方法之外可以直接借助名字使用,当前类的main方法中可以使用对象打点的方式直接使用成员
    • 2.在当前类之外,使用对象(或是类名,针对静态的)打点调用都是被限制的。可以通过在当前类中开发一个公有的方法(getter,setter),在公有方法中可以使用这个私有的成员,从而达到间接使用私有成员
    • 在继承中,私有成员禁止被继承,也就是说在子类的开发中,拒绝直接使用私有成员的名字进行使用
  • public

    • 1.在当前类开发中,main方法之外可以直接借助名字使用,当前类的main方法中可以使用对象打点的方式直接使用成员
    • 2.在当前类之外,使用对象(或是类名,针对静态的)打点调用是被允许的
    • 3.在子类中,公有成员允许被继承,也就是说在子类的开发中,可以直接使用公有成员的名字进行使用
  • protected

    • 同一个包的情况:
      • 1.在当前类开发中,main方法之外可以直接借助名字使用,当前类的main方法中可以使用对象打点的方式直接使用成员
      • 2.在当前类之外,同一个包中,使用对象(或是类名,针对静态的)打点调用是被允许的
      • 3.在子类中,同一个包中,受保护成员允许被继承,也就是说在子类的开发中,可以直接使用受保护成员的名字进行使用。子类的main方法中可以使用子类或是父类对象打点调用
      • 4.在当前类之外,子类之外,要使用子类的类中,同一个包中,可以使用子类或是父类对象打点调用。
    • 不同包的情况:
      • 1.在当前类之外,不同包中,使用对象(或是类名,针对静态的)打点调用是被禁止的
      • 2.在子类中,不同包中,受保护成员允许被继承,也就是说在子类的开发中,可以直接使用受保护成员的名字进行使用。子类的main方法中只能通过子类对象打点调用。父类对象不行,这个时候相当于父类中的受保护成员跨包了
      • 3.在当前类之外,子类之外,要使用子类的类中,与子类同一个包中,通过子类对象打点是调用不出父类中的受保护的成员的。父类对象更不行,这个时候相当于父类中的受保护成员跨包了。如果想要通过子类对象调用父类的受保护的成员,需要重新覆写父类的这个成员
      • 4.在当前类之外,子类之外,要使用子类的类中,与父类同一个包中,通过子类对象打点是可以调用父类中的受保护的成员的。父类对象也行,同个包中
      • 5.在与父类和子类都不同包的第三个包中,要想通过子类对象调用父类的受保护成员,可以通过覆写父类受保护成员,并将访问限制符修改成public
  • 总结
    在这里插入图片描述

Java继承

继承特性

  • 子类拥有父类非 private 的属性、方法
  • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展
  • 子类可以用自己的方式实现父类的方法
  • Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性
  • 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)

继承关键字

  • extends
    • 在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类
    public class base{
    }
    public class child extends base{
    }
    
  • implements
    • 使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)
    public interface A {
    }
    public interface B {
    }
    public class C implements A,B {
    }
    
  • super和this
    • 通过super关键字来实现对父类成员的访问,用来引用当前对象的父类
    • this指向自己的引用
    public class Animal{
    	public void eat(){
    	}
    }
    public class Dog extends Animal{
    	public void eat(){
    	}
    	public void test(){
    		this.eat();
    		super.eat();
    	}
    }
    
  • final
    • final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写
    • 声明类,不能被继承
    final class ClassName{
    }
    
    • 声明方法,不能被子类重写
    修饰符(public/private/default/protected) final 返回类型 方法名(){// method}
    

构造器

  • 子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表
  • 如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器
    class SuperClass {
    	private int n;
    	SuperClass(){
    		System.out.println("SuperClass()");
    	}
      	SuperClass(int n) {
        	System.out.println("SuperClass(int n)");
        	this.n = n;
        }
    }
    // SubClass 类继承
    class SubClass extends SuperClass{
    	private int n;
      
    	SubClass(){ // 自动调用父类的无参数构造器
        	System.out.println("SubClass");
        }  
    
    	public SubClass(int n){ 
    		super(300);  // 调用父类中带有参数的构造器
    		System.out.println("SubClass(int n):"+n);
    		this.n = n;
    	}
    }
    

继承类型

  • Java支持多重继承,但不支持多继承
  • 可以通过接口类(interface)和implements关键字变相使java具有多继承的特性
    在这里插入图片描述

Java多态

  • 多态的优点
    • 消除类型之间的耦合关系
    • 可替换性
    • 可扩充性
    • 接口性
    • 灵活性
    • 简化性
  • 多态存在的三个必要条件
    • 继承
    • 重写
    • 父类引用指向子类对象:Parent p = new Child();
  • 当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法
  • 多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理
  • 虚函数:虚函数的存在是为了多态。
  • Java 中其实没有虚函数的概念,它的普通函数就相当于 C++ 的虚函数,动态绑定是Java的默认行为如果 Java 中不希望某个函数具有虚函数特性,可以加上 final 关键字变成非虚函数

Java抽象类(与C++一致)

  • 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类
  • 抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样
  • 由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类
  • 父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法
  • 在Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口

定义、继承抽象类

public abstract class Base{		// 定义抽象类
}
public class Child extends Base{	// 继承抽象类
}

抽象方法

  • 如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法
  • Abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体
  • 抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号
public class ClassName{
	public abstract void method();
	// other
}
  • 声明抽象方法会造成以下两个结果:
    • 如果一个类包含抽象方法,那么该类必须是抽象类
    • 任何子类必须重写父类的抽象方法,或者声明自身为抽象类
  • 继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象

抽象类总结

  1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象

  2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类

  3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能

  4. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法

  5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类

Java接口

  • 接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法
  • 接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法
  • 除非实现接口的类是抽象类,否则该类要定义接口中的所有方法
  • 接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象
  • 接口与类相似点:
    • 一个接口可以有多个方法
    • 接口文件保存在 .java 结尾的文件中,文件名使用接口名
    • 接口的字节码文件保存在 .class 结尾的文件中
    • 接口相应的字节码文件必须在与包名称相匹配的目录结构中
  • 接口与类的区别:
    • 接口不能用于实例化对象
    • 接口没有构造方法
    • 接口中所有的方法必须是抽象方法
    • 接口不能包含成员变量,除了 static 和 final 变量
    • 接口不是被类继承了,而是要被类实现
    • 接口支持多继承
  • 接口特性
    • 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)
    • 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)
    • 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法
  • 抽象类和接口的区别
    1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行
    2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的
    3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法
    4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口(实现多继承)

接口声明

// 声明模板
[可见度] interface 接口名称 [extends 其他的接口名] {
        // 声明static、final字段
        // 抽象方法
}

/* 文件名 : Animal.java */
interface Animal {
   public void eat(); // 隐式抽象方法,不用abstract
   public void travel();
}

重写接口声明方法的规则

  • 重写接口中声明的方法时,需要注意以下规则:
    • 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常
    • 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型
    • 如果实现接口的类是抽象类,那么就没必要实现该接口的方法
  • 在实现接口的时候,也要注意一些规则:
    • 一个类可以同时实现多个接口
    • 一个类只能继承一个类,但是能实现多个接口
    • 一个接口能继承另一个接口,这和类之间的继承比较相似

接口(多)继承

  • 接口继承
// 文件名: Sports.java
public interface Sports
{
   public void setHomeTeam(String name);
   public void setVisitingTeam(String name);
}
 
// 文件名: Football.java
public interface Football extends Sports
{
   public void homeTeamScored(int points);
   public void visitingTeamScored(int points);
   public void endOfQuarter(int quarter);
}
 
// 文件名: Hockey.java
public interface Hockey extends Sports
{
   public void homeGoalScored();
   public void visitingGoalScored();
   public void endOfPeriod(int period);
   public void overtimePeriod(int ot);
}
/*
Hockey接口自己声明了四个方法,从Sports接口继承了两个方法,这样,实现Hockey接口的类需要实现六个方法。
相似的,实现Football接口的类需要实现五个方法,其中两个来自于Sports接口
*/
  • 多继承
public interface Hockey extends Sports, Event
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值