文章目录
一、包
1.包的概述
包是组织类的方式,使用包的主要目的是保证类的唯一性。
路径不同,则就是唯一的,例如:同事与你写了一个同样名字的类,就会导致冲突,导致编译无法通过
包其实是一个文件夹
2.使用系统包
1.使用导入包的方式来使用系统包
在java文件夹中有这样一个文件(一般为压缩文件,这是解压后文件),储存着java的源代码中的包
像这种头文件叫做导入包
使用*的时候,导入所有的包(你使用那个包时自动导入)
2.不使用系统包的方式来导入包
例:
使用这种方式来进行导入,标明好路径。
3.重复包的使用
import java.util.*;
import java.sql.*;
在这两个包中同时拥有Date这个类,会导致歧义,以至于编译器无法识别,在这种情况下,就不能使用导入系统包的方式来进行,而必须写完整的类名
4.导入静态包(不建议)
import static java.lang.System.*;
这种导入是静态导入导入这种包后,常使用的打印函数就可以这样写
out.println("haha");
5.常用的系统
import java.lang.*;//系统常用的基础类(String、Object),此包从JDK1.1后自动导入。
import java.lang.reflect.*;//反射编程包;
import java.net.*;//进行网络编程的开发包
import java.sql.*;//进行数据库编程的开发包
import java.util.*;//是java提供的工具程序包。(集合类等)
import java.io.*;//I/O编程开发包。
二、继承(extends)
1.继承初理解
在编写类时,可能会有很多相同的属性及方法。
例:
class dog{
public String name;
public int age;
public void eat(){
System.out.println("chi()");
}
public void crow(){
System.out.println("wangwang");
}
}
class cat{
public String name;
public int age;
public void eat(){
System.out.println("chi()");
}
public void fly(){
System.out.println("fly()");
}
}
这时候就可以使用继承,把相同的属性或方法包装起来,其他类来继承
class animal{
public String name;
public int age;
public void eat(){
System.out.println("chi()");
}
}
class dog extends animal{
public void crow(){
System.out.println("wangwang");
}
}
class bird extends animal{
public void fly(){
System.out.println("fly()");
}
}
在上述例子中:
dog类extends了animal
这时
dog:子类 、 派生类
animal:父类、基类、超类
2.继承的好处
可以进行代码的复用。
3.private修饰参数
若父类方法中有参数或方法是被private修饰,则使用时不能进行使用。
class animal{
private String name;
public int age;
public void eat(){
System.out.println("chi()");
}
}
public static void main(String[] args) {
Dog dog = new Dog();
System.out.println(dog.name+"hh");
}
此时调用时则会进行报错。
4.(面试问题)子类继承了父类那些东西?
答:除构造方法之外的所有都被继承了。
5.super关键字
子类的构造需要先帮助父类对象进行构造(调用父类的构造方法)。
class Animal{
private String name;
public int age;
public void eat(){
System.out.println("chi()");
}
public Animal(String name){
this.name=name;
}
}
class Dog extends Animal{
public String sex;
public Dog(String name,String sex){
super(name); //注:用super来给父类构造时要放到第一行,否则会报错。
this.sex=sex;
}
public void crow(String name){
System.out.println("wangwang");
}
}
否则程序会进行报错。
super的三种使用方式:
- super():调用父类的构造方法(必须放到第一行)
- super.data:调用父类的成员属性
- super.func:调用父类的成员方法
6.代码的执行顺序
- 父类的static{}
- 子类的static{}
- 父类的实例代码块{}
- 父类的构造函数
- 子类的实例代码块{}
- 子类的构造函数
静态的一定先执行,只执行一次。
7.复杂的继承关系
class A{
}
class B extends A{
}
class C extends B{
}
class D extends C{
}
注:这种继承关系最多不要超过三层,若不想被继承需要使用final来修饰来防止不被继承。
8.继承的注意事项
- 使用extends
- Java中一个子类,只能继承一个父类
- 子类会继承父类的所有public的字段和方法
- 对于父类的private方法和字段,子类是无法访问的(并不是无法继承)
9.继承时,相同名属性的分布
class A{
public int a = 1;
}
class B extends A{
public int a = 2;
public int b = 3;
}
public class testw {
public static void main(String[] args) {
B b = new B();
System.out.println(b.a);
}
}
这种时候的调用a时,会调用子类的a,而不会调用父类的a。
三、访问修饰限定符
public :公共权限
所有的文件都可以进行访问
private,:私有权限
只有在当前类中可以进行访问
protected:受保护权限
在继承时使用,在父类中有protected的属性或方法在不同包中子类继承父类时可以进行调用,使用super关键字进行调用
default:默认包访问权限
只能在当前包中进行访问
四、final:
- final来修饰常量,int a = 10;
- final来修饰类,final class A {},这个类叫做密封类,不想被继承时使用。
- final来修饰方法,这个方法叫做密封方法。
五、组合
像下面这种关系就叫组合
class Student{ //类
}
class teacher{ //类
}
class school{
public Student[] student;
public teacher[] teacher;
}
六、多态
字面意思:一种事物多种形态
1.向上转型
子类对象给父类
Animal animal = new Dog("张三");
注意问题:
在Dog子类对象中创建 变量a;
在Animal父类中创建 变量b;
Animal animal = new Dog("张三");
System.out.println(animal.b);
System.out.println(animal.a); //报错,父类对象无法调用子类对象
Dog dog = new Dog("李四");
System.out.println(dog.b);
System.out.println(dog.a);
此时animal的类型是Animal,所以只能访问Animal类自己的成员。
向上转型的三个时机:
- 直接赋值:
Animal animal = new Dog("张三");
- 传值:
public static void main(String[] args) {
func(animal); //这三种发生向上转型
func(dog);
func(new Dog("王五"));
}
public static void func(Animal animal){
}
- 返回值:
public static void main(String[] args) {
Animal animal1 = func1();
}
public static Animal func1(){
Dog dog = new Dog("张三");
return dog;
}
2.向下转型
父类对象给子类
public static void main(String[] args) {
Animal animal = new Dog("张三");
Dog dog = (Dog) animal;
dog.crow();
}
注意事项:
public static void main(String[] args) {
Animal animal = new Animal("张三");
Dog dog = (Dog) animal;
dog.crow();
}
此时代码会进行报错,回报一个类型转换错误
所以说向下转型,必须要进行向上转型。
避免错修改:
//判断一下animal 是不是 Dog 的实例。
if(animal instanceof Dog){
Dog dog = (Dog) animal;
dog.crow();
}
如果animal引用了Dog则返回true,否则false。
这样就安全了。
3.重写
class Animal{
public void eat(){
System.out.println("chi()");
}
}
class Dog extends Animal{
@Override //注解:标识在这里发生了重写
public void eat() {
System.out.println("he()");
}
}
public static void main(){
Animal animal = new Dog("花花");
animal.eat();
}
重载(overload)
1.方法名相同
2.参数列表不同(个数和类型)
3.返回值不做要求
重写(override)
1.方法名相同
2.参数列表相同(个数和类型)
3.返回值相同(若返回值构成协变类型)
协变类型:子类的返回值与父类之间返回值是继承关系
class Animal{
public Animal eat(){
System.out.println("chi()");
return new Animal("小花");
}
}
class Dog extends Animal{
@Override
public Dog eat() {
System.out.println("he()");
return new Dog("huahua");
}
}
此时就构成了协变类型
动态绑定:
1.一定要发生向上转型
2.父类和子类有同名的重写(覆写/覆盖)方法
3.最后通过父类的引用来调用子类和父类的这个同名的覆盖方法。
此时会发生动态绑定,或者叫做运行时绑定。
注意: 在构造函数中也可以发生动态绑定(一个坑)
class Animal{
public void eat(){
System.out.println("chi()");
}
public Animal(String name){
eat(); //发生动态绑定
this.name=name;
}
}
class Dog extends Animal{
public Dog(String name){
super(name);
}
public void eat() {
System.out.println("he()");
}
}
public static void main(String[] args) {
Animal animal = new Dog("花花");
}
此时在父类构造方法中发生动态绑定
重写的注意事项
1.如果当前方法是静态方法,是不可以被重写的
2.子类如果要重写父类方法,那么子类的访问修饰权限要大于等于父类的权限
3.父类中要被重写的方法一定不能是,private(私有)。
4.被final修饰的方法不能被重写(密封方法)。
4.理解多态
class Shape{
public void draw(){
}
}
class Cycle extends Shape{
public void draw(){ //来重写父类方法
System.out.println("矩形");
}
}
class Rect extends Shape{
public void draw(){ //重写父类方法
System.out.println("圆形");
}
}
public class testDome {
public static void drawMap(Shape shape){
shape.draw(); //调用父类方法,子类方法进行重写发生动态绑定打印子类方法
}
public static void main(String[] args) {
Cycle cycle = new Cycle(); //new子类对象
Rect rect = new Rect(); //new子类对象
drawMap(cycle); //传参时发生向上转型
drawMap(rect); //传参时发生向上转型
}
}
七、抽象类
包含抽象方法的类就是抽象类
抽象方法是什么:被关键字abstract修饰的方法,这个方法可以没有具体的实现。
abstract class Shape{ //密封类
public abstract void draw(); //密封方法
}
抽象类的注意事项
- 抽象类可以被继承,也可以发生动态绑定,向上转型。
- 抽象类不可以被实例化
- 抽象类中的方法一定要被子类重写
- 抽象类存在的意义就是为了被继承,因为不能被实例化
- 如果一个抽象类继承了抽象类,那么可以不重写这个抽象方法。但是这个抽象类再次被一个普通类继承,就需要重写抽象方法。
- 抽象方法不能是private
- 可以包含普通的方法
- 抽象类不能被final修饰。
八、接口
使用关键字interface来修饰的。
1.接口的细节
- 接口当中的方法默认是public abstract 不能有具体实现
- 接口不能实例化
- 接口当中的方法 默认是public static final
- 类和接口直接的关系是implements,此时接口中的所有方法,都要被重写。
- 接口也可以发生向上转型 - 》 运行时绑定(动态绑定)
- JDK1.8开始,接口当中的方法可以有具体的实现,但这个方法一定要被default修饰。
- 在Java中一个类可以实现多个接口。
- 类和接口是implements,接口和接口之间是extends
interface IShape{ //接口
int a = 10; //参数默认为 public static final
void draw(); //方法默认为 public abstract
default void func1(){ //jdk1.8开始接口中方法有具体的实现,这个方法一定要被default修饰。
System.out.println("123");
}
}
class Cycle implements IShape{
@Override
public void draw(){
System.out.println("○");
}
}
public class testDome {
public static void func(IShape iShape){
iShape.draw();
}
public static void main(String[] args) {
//IShape iShape = new IShape(); //不能进行实例化
IShape iShape = new Cycle(); //发生向上转型
func(iShape);
}
}
interface A{
}
interface B{
}
interface C extends A,B{
}
2.Comparable接口
在使用自定义类型时要使用Comparable接口
class Student implements Comparable<Student>{
public String name;
public int age;
public Student(String name,int age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) { //对自定义的数据进行排序
//比较的规则
/*if (this.age > o.age){
return 1; //正值
}else if (this.age > o.age){
return -1;
}else{
return 0;
}*/
//return this.age - o.age; //简化方法
return this.name.compareTo(o.name); //在String中实习了compareTo方法
}
}
public class testDome {
public static void main(String[] args) {
Student[] student = new Student[3];
student[0] = new Student("caocao",18);
student[1] = new Student("liubei",26);
student[2] = new Student("sunquan",22);
Arrays.sort(student); //数组排序
System.out.println(Arrays.toString(student)); //数组打印
}
}
3.比较器(Comparator)
//类同上面Student不实现接口。
//同包不同类
public class AgeComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return o1.age-o2.age;
}
}
//同包不同类
public class NameComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
}
//主程序
public static void main(String[] args) {
Student[] student = new Student[3];
student[0] = new Student("caocao",18);
student[1] = new Student("liubei",26);
student[2] = new Student("sunquan",22);
NameComparator nameComparator = new NameComparator();
Arrays.sort(student,nameComparator);
System.out.println(Arrays.toString(student));
}
使用比较器更方便,你想使用什么比较就自己实现一个比较器。
相比于Comparable来说,一旦类写死了一种比较方式那么就不能轻易修改了
3.Cloneable接口
Cloneable接口是一个空接口(标识接口),只是代表这个类是可以被克隆的。
class Student1 implements Cloneable{ //这个接口代表着这个类可以被克隆
public String name;
public int age;
public Student1(String name,int age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//Override Methods 中的clone
@Override
protected Object clone() throws CloneNotSupportedException { //接口中没有clone方法,所以需要重写Object的方法
Student1 student1 = (Student1) super.clone(); //调用父类的克隆方法给了Student1
return student1;
}
}
public class testDome1 {
public static void main(String[] args) throws CloneNotSupportedException {
Student1 student1 = new Student1("caocao",18);
Student1 student2 = (Student1)student1.clone();
System.out.println(student1);
System.out.println(student2);
}
}
Cloneable中深浅拷贝问题:
浅拷贝
class Part implements Cloneable{
public int m = 10;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Student1 implements Cloneable{ //这个接口代表着这个类可以被克隆
public String name;
public int age;
public Part a;
public Student1(String name,int age){
this.name = name;
this.age = age;
this.a = new Part();
}
@Override
public String toString() {
return "Student1{" +
"name='" + name + '\'' +
", age=" + age +
", a=" + a +
'}';
}
//Override Methods 中的clone
@Override
protected Object clone() throws CloneNotSupportedException { //接口中没有clone方法,所以需要重写Object的方法
Student1 student1 = (Student1) super.clone(); //调用父类的克隆方法给了Student1
student1.a = (Part)this.a.clone();
return student1;
}
}
public class testDome1 {
public static void main(String[] args) throws CloneNotSupportedException {
Student1 student1 = new Student1("caocao",18);
Student1 student2 = (Student1)student1.clone();
System.out.println(student1);
System.out.println(student2);
}
}
以上方法是更改浅拷贝为深拷贝