Java教程

JAVA笔记

本文主要是介绍JAVA笔记,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

对象

概述

Java是一种面向对象的高级编程语言。

三大特征:封装,继承,多态

面向对象最重要的两个概念:类和对象

  • 类:相同事物共同特征的描述。类只是学术上的一个概念并非真实存在的,只能描述一类事物
  • 对象:是真实存在的实例, 实例==对象,对象是类的实例化
  • 结论:有了类和对象就可以描述万千世界所有的事物。 必须先有类才能有对象

定义

定义格式

修饰符 class 类名{
}
  1. 类名的首字母建议大写,满足驼峰模式,比如 StudentNameCode
  2. 一个 Java 代码中可以定义多个类,按照规范一个 Java 文件一个类
  3. 一个 Java 代码文件中,只能有一个类是 public 修饰,public修饰的类名必须成为当前Java代码的文件名称
类中的成分:有且仅有五大成分
修饰符 class 类名{
		1.成员变量(Field):  	描述类或者对象的属性信息的。
        2.成员方法(Method):		描述类或者对象的行为信息的。
		3.构造器(Constructor):	 初始化一个对象返回。
		4.代码块
		5.内部类
	  }
类中有且仅有这五种成分,否则代码报错!
public class ClassDemo {
    System.out.println(1);//报错
}

构造器

构造器格式:

修饰符 类名(形参列表){

}

作用:初始化类的一个对象返回

分类:无参数构造器,有参数构造器

注意:一个类默认自带一个无参数构造器,写了有参数构造器默认的无参数构造器就消失,还需要用无参数构造器就要重新写

构造器初始化对象的格式:类名 对象名称 = new 构造器

  • 无参数构造器的作用:初始化一个类的对象(使用对象的默认值初始化)返回
  • 有参数构造器的作用:初始化一个类的对象(可以在初始化对象的时候为对象赋值)返回

包:分门别类的管理各种不同的技术,便于管理技术,扩展技术,阅读技术

定义包的格式:package 包名,必须放在类名的最上面

导包格式:import 包名.类名

相同包下的类可以直接访问;不同包下的类必须导包才可以使用


封装

封装的哲学思维:合理隐藏,合理暴露
封装最初的目的:提高代码的安全性和复用性,组件化

封装的步骤:

  1. 成员变量应该私有,用 private 修饰,只能在本类中直接访问
  2. 提供成套的 getter 和 setter 方法暴露成员变量的取值和赋值

使用 private 修饰成员变量的原因:实现数据封装,不想让别人使用修改你的数据,比较安全


this

this 关键字的作用:

  • this 关键字代表了当前对象的引用
  • this 出现在方法中:哪个对象调用这个方法 this 就代表谁
  • this 可以出现在构造器中:代表构造器正在初始化的那个对象
  • this 可以区分变量是访问的成员变量还是局部变量

static

基本介绍

Java 是通过成员变量是否有 static 修饰来区分是类的还是属于对象的。

static 静态修饰的成员(方法和成员变量)属于类本身的。

按照有无 static 修饰,成员变量和方法可以分为:

  • 成员变量:

    • 静态成员变量(类变量):static 修饰的成员变量,属于类本身,与类一起加载一次,只有一个,直接用类名访问即可
    • 实例成员变量:无 static 修饰的成员变量,属于类的每个对象的,与类的对象一起加载,对象有多少个,实例成员变量就加载多少个,必须用类的对象来访问
  • 成员方法:

    • 静态方法:有 static 修饰的成员方法称为静态方法也叫类方法,属于类本身的,直接用类名访问即可
    • 实例方法:无 static 修饰的成员方法称为实例方法,属于类的每个对象的,必须用类的对象来访问

static用法

成员变量的访问语法:

  • 静态成员变量:只有一份可以被类和类的对象共享访问

    • 类名.静态成员变量(同一个类中访问静态成员变量可以省略类名不写)
    • 对象.静态成员变量(不推荐)
  • 实例成员变量:

    • 对象.实例成员变量(先创建对象)

成员方法的访问语法:

  • 静态方法:有 static 修饰,属于类

    • 类名.静态方法(同一个类中访问静态成员可以省略类名不写)
    • 对象.静态方法(不推荐,参考 JVM → 运行机制 → 方法调用)
  • 实例方法:无 static 修饰,属于对象

    • 对象.实例方法
    public class Student {
        // 1.静态方法:有static修饰,属于类,直接用类名访问即可!
        public static void inAddr(){ }
        // 2.实例方法:无static修饰,属于对象,必须用对象访问!
        public void eat(){}
        
        public static void main(String[] args) {
            // a.类名.静态方法
            Student.inAddr();
            inAddr();
            // b.对象.实例方法
            // Student.eat(); // 报错了!
            Student zbj = new Student();
            zbj.eat();
        }
    }
    

两个问题

内存问题:

  • 栈内存存放 main 方法和地址

  • 堆内存存放对象和变量

  • 方法区存放 class 和静态变量(jdk8 以后移入堆)

访问问题:

  • 实例方法是否可以直接访问实例成员变量?可以的,因为它们都属于对象
  • 实例方法是否可以直接访问静态成员变量?可以的,静态成员变量可以被共享访问
  • 实例方法是否可以直接访问实例方法? 可以的,实例方法和实例方法都属于对象
  • 实例方法是否可以直接访问静态方法?可以的,静态方法可以被共享访问
  • 静态方法是否可以直接访问实例变量? 不可以的,实例变量必须用对象访问!!
  • 静态方法是否可以直接访问静态变量? 可以的,静态成员变量可以被共享访问。
  • 静态方法是否可以直接访问实例方法? 不可以的,实例方法必须用对象访问!!
  • 静态方法是否可以直接访问静态方法?可以的,静态方法可以被共享访问!!

继承

基本介绍

继承是 Java 中一般到特殊的关系,是一种子类到父类的关系

  • 被继承的类称为:父类/超类。
  • 继承父类的类称为:子类。

继承的作用:

  • 提高代码的复用,相同代码可以定义在父类中
  • 子类继承父类,可以直接使用父类这些代码(相同代码重复利用)
  • 子类得到父类的属性(成员变量)和行为(方法),还可以定义自己的功能,子类更强大

继承的特点:

  1. 子类的全部构造器默认先访问父类的无参数构造器,再执行自己的构造器
  2. 单继承:一个类只能继承一个直接父类
  3. 多层继承:一个类可以间接继承多个父类(家谱)
  4. 一个类可以有多个子类
  5. 一个类要么默认继承了 Object 类,要么间接继承了 Object 类,Object 类是 Java 中的祖宗类

继承的格式:

子类 extends 父类{

}

子类不能继承父类的东西:

  • 子类不能继承父类的构造器,子类有自己的构造器
  • 子类是不能可以继承父类的私有成员的,可以反射暴力去访问继承自父类的私有成员
  • 子类是不能继承父类的静态成员的,子类只是可以访问父类的静态成员,父类静态成员只有一份可以被子类共享访问,共享并非继承
public class ExtendsDemo {
    public static void main(String[] args) {
        Cat c = new Cat();
        // c.run();
        Cat.test();
        System.out.println(Cat.schoolName);
    }
}
class Cat extends Animal{
}
class Animal{
    public static String schoolName ="seazean";
    public static void test(){}
    private void run(){}
}

变量访问

继承后成员变量的访问特点:就近原则,子类有找子类,子类没有找父类,父类没有就报错

如果要申明访问父类的成员变量可以使用:super.父类成员变量,super指父类引用

public class ExtendsDemo {
    public static void wmain(String[] args) {
        Wolf w = new Wolf();w
        w.showName();
    }
}
class Wolf extends Animal{
    private String name = "子类狼";
    public void showName(){
        String name = "局部名称";
        System.out.println(name); // 局部name
        System.out.println(this.name); // 子类对象的name
        System.out.println(super.name); // 父类的
        System.out.println(name1); // 父类的
        //System.out.println(name2); // 报错。子类父类都没有
    }
}

class Animal{
    public String name = "父类动物名称";
    public String name1 = "父类";
}

方法访问

子类继承了父类就得到了父类的方法,可以直接调用,受权限修饰符的限制,也可以重写方法

方法重写:子类重写一个与父类申明一样的方法来覆盖父类的该方法

方法重写的校验注解:@Override

  • 方法加了这个注解,那就必须是成功重写父类的方法,否则报错
  • @Override 优势:可读性好,安全,优雅

子类可以扩展父类的功能,但不能改变父类原有的功能,重写有以下三个限制:

  • 子类方法的访问权限必须大于等于父类方法
  • 子类方法的返回类型必须是父类方法返回类型或为其子类型
  • 子类方法抛出的异常类型必须是父类抛出异常类型或为其子类型

继承中的隐藏问题:

  • 子类和父类方法都是静态的,那么子类中的方法会隐藏父类中的方法
  • 在子类中可以定义和父类成员变量同名的成员变量,此时子类的成员变量隐藏了父类的成员变量,在创建对象为对象分配内存的过程中,隐藏变量依然会被分配内存
public class ExtendsDemo {
    public static void main(String[] args) {
        Wolf w = new Wolf();
        w.run();
    }
}
class Wolf extends Animal{
    @Override
    public void run(){}//
}
class Animal{
    public void run(){}
}

面试问题

  • 为什么子类构造器会先调用父类构造器?

    1. 子类的构造器的第一行默认 super() 调用父类的无参数构造器,写不写都存在
    2. 子类继承父类,子类就得到了父类的属性和行为。调用子类构造器初始化子类对象数据时,必须先调用父类构造器初始化继承自父类的属性和行为
    3. 参考 JVM → 类加载 → 对象创建
    class Animal{
        public Animal(){
            System.out.println("==父类Animal的无参数构造器==");
        }
    }
    class Tiger extends Animal{
        public Tiger(){
            super(); // 默认存在的,根据参数去匹配调用父类的构造器。
            System.out.println("==子类Tiger的无参数构造器==");
        }
        public Tiger(String name){
            //super();  默认存在的,根据参数去匹配调用父类的构造器。
            System.out.println("==子类Tiger的有参数构造器==");
        }
    }
    
  • 为什么 Java 是单继承的?

    答:反证法,假如 Java 可以多继承,请看如下代码:

    class A{
    	public void test(){
    		System.out.println("A");
    	}
    }
    class B{
    	public void test(){
    		System.out.println("B");
    	}
    }
    class C extends A , B {
    	public static void main(String[] args){
    		C c = new C();
            c.test(); 
            // 出现了类的二义性!所以Java不能多继承!!
    	}
    }
    

super

继承后 super 调用父类构造器,父类构造器初始化继承自父类的数据。

总结与拓展:

  • this 代表了当前对象的引用(继承中指代子类对象):this.子类成员变量、this.子类成员方法、this(...)可以根据参数匹配访问本类其他构造器。
  • super 代表了父类对象的引用(继承中指代了父类对象空间):super.父类成员变量、super.父类的成员方法、super(...)可以根据参数匹配访问父类的构造器

注意:

  • this(...) 借用本类其他构造器,super(...) 调用父类的构造器。
  • this(...) 或 super(...) 必须放在构造器的第一行,否则报错!
  • this(...) 和 super(...) 不能同时出现在构造器中,因为构造函数必须出现在第一行上,只能选择一个。
public class ThisDemo {
    public static void main(String[] args) {
        // 需求:希望如果不写学校默认就是”张三“!
        Student s1 = new Student("天蓬元帅", 1000 );
        Student s2 = new Student("齐天大圣", 2000, "清华大学" );
    }
}
class Study extends Student {
   public Study(String name, int age, String schoolName) {
        super(name , age , schoolName) ; 
       // 根据参数匹配调用父类构造器
   }
}

class Student{
    private String name ;
    private int age ;
    private String schoolName ;

    public Student() {
    }
    public Student(String name , int age){
        // 借用兄弟构造器的功能!
        this(name , age , "张三");
    }
	public Student(String name, int age, String schoolName) {
        this.name = name;
        this.age = age;
        this.schoolName = schoolName;
    }
// .......get + set
}

final

基本介绍

final 用于修饰:类,方法,变量

  • final 修饰类,类不能被继承了,类中的方法和变量可以使用
  • final 可以修饰方法,方法就不能被重写
  • final 修饰变量总规则:变量有且仅能被赋值一次

面试题:final 和 abstract 的关系是互斥关系,不能同时修饰类或者同时修饰方法!


修饰变量

静态变量

final 修饰静态成员变量,变量变成了常量

常量:有 public static final 修饰,名称字母全部大写,多个单词用下划线连接。

final 修饰静态成员变量可以在哪些地方赋值:

  1. 定义的时候赋值一次

  2. 可以在静态代码块中赋值一次

public class FinalDemo {
//常量:public static final修饰,名称字母全部大写,下划线连接。
    public static final String SCHOOL_NAME = "张三" ;
    public static final String SCHOOL_NAME1;

    static{
        //SCHOOL_NAME = "java";//报错
        SCHOOL_NAME1 = "张三1";
        //SCHOOL_NAME1 = "张三2"; // 报错,第二次赋值!
    }
}
实例变量

final 修饰变量的总规则:有且仅能被赋值一次

final 修饰实例成员变量可以在哪些地方赋值 1 次:

  1. 定义的时候赋值一次
  2. 可以在实例代码块中赋值一次
  3. 可以在每个构造器中赋值一次
public class FinalDemo {
    private final String name = "张三" ;
    private final String name1;
    private final String name2;
    {
        // 可以在实例代码块中赋值一次。
        name1 = "张三1";
    }
	//构造器赋值一次
    public FinalDemo(){
        name2 = "张三2";
    }
    public FinalDemo(String a){
        name2 = "张三2";
    }

    public static void main(String[] args) {
        FinalDemo f1 = new FinalDemo();
        //f1.name = "张三1"; // 第二次赋值 报错!
    }
}
这篇关于JAVA笔记的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!