ENDING的java笔记

java学习笔记

第一阶段

chapter04 运算符

键盘输入

  • Sacnner类表示 简单文本扫描器,在Java.util包
    • 1、引入/导入Scanner类所在的包
    • 2、创建Scanner对象,new创建一个对象

代码演示:

import java.util.Scanner;

public class test{
	public static void main (String args[]){

		Scanner myScanner = new Scanner(System.in);

		System.out.println("输入名字:");
		String name = myScanner.next();
		System.out.println("姓名:" + name);
		System.out.println("输入年龄:");
		int age = myScanner.nextInt();
		System.out.println("年龄:" + age);
        char gender = myScanner.next().charAt(0); 		//从字符串中获取字符
	}
}

String类型转换为double等类型

代码演示:

//string转double
public class BitOperator{
	public static void main(String args[]){
		String str = "123.4";
		Double num1 = Double.parseDouble(str);
		System.out.println(num1);
	}
}

//char转string
public class BitOperator{

	public static void main(String args[]){
		char c = 'h';
        Sring str = c + "";
        System.out.println(str);
	}
}

chapter05 程序控制

Switch-case语句

细节

  • Switch(表达式)中表达式的返回值必须是:byte,short,int ,char,enum,String

  • case子句中的值必须是常量(例如1,‘a’)或者常量表达式而不能是变量

  • break语句用来执行完最后一个case分支后使程序跳出Switch语句块

代码演示:

import java.util.Scanner;

public class Switchcase{
	public static void main(String args[]){
		Scanner myScanner = new Scanner(System.in);

		int a = myScanner.nextInt();
		switch(a){
		case 1:
			System.out.println("星期1");
			break;
		case 2:
			System.out.println("星期2");
			break;
		default:
			System.out.println("无匹配项");
		}
	}
}

跳转控制语句break-lable

  • 当break语句出现在多层嵌套循环时,可以通过标签指明要终止的是哪一层语句块
  • 实际应用中尽量避免使用标签(lable),易造成逻辑混乱

代码演示:

public class breaklable{
	public static void main(String[] args){
		lable1:
		for(int i = 0 ;i < 10; i++){
			lable2:
			for(int j = 0 ; j < 10 ; j ++){
				lable3:
				for(int k = 0 ;k < 10 ;k ++){
					if(i * j  + k == 25){
						System.out.println("i = " + i + " j = " + j + " k = " + k + "hhhh");
						break lable2;
					}
					System.out.println("i = " + i + " j = " + j + " k = " + k);
				}
			}
		}
	}
}

chapter06 数组,排序,查找

数组array

  • 可通过 array.length 来获得数组长度
  • int[] array 等价于 int array[]
  • 数组默认初始化为0
  • Stirng array[] = {“abc” , “bcd” , “efg”} 静态初始化 字符串数组
  • 开辟自定义长度数组有以下两种写法
//创建长度为5的数组
double array[] = new double[5];

//先声明,再分配空间
double array[];
array = new double[5];			//动态初始化
  • 数组赋值实际上是地址赋值,例如:
int array1[] = {1,2,3};
int array2[] = array1;

array2[0] = 10;
//此时array1中的array[0]值也被修改为10
  • 数组翻转

    • 开辟一个新数组,将原数组翻转后,原数组指向第二个数组,则原数组会被回收

      int array1[] = {1,2,3,4,5,6};
      int len = array1.length;
      int array2[] = new int[len];
      for(int i = 0 ;i < len ; i++){
          array2[i] = array1[len - i - 1];
      }
      array1 = array2;
      

字符串比较

  • 顺序查找
import java.util.Scanner;

public class array01{
	public static void main(String[] args){
		Scanner myScanner = new Scanner(System.in);
		String name[] = {"abc" , "efd" , "hij"};

		String findname = myScanner.next();
		for(int i = 0 ;i < name.length ; i++){
			if(findname.equals(name[i])){			//使用equals来比较
				System.out.println("该字符串存在");
			}
		}
	}
}

二维数组

  • 二维数组可以定义为int array[5] [ ]例如,每一行数据长度可不同

    int array[][] = new int [5][];
    for(int i = 0; i < 5 ; i++){
        array[i] = new int[i];
    }
    
    //这种写法也支持,每行元素个数可不一致
    int arr[][] = new int[3][];
    arr[0] = new int[4];
    arr[1] = new int[3];
    arr[2] = new int[5];
    
  • 有int [] []array 和int [] array[]和 int arary[] []三种声明方法

随机数

使用方法

import java.util.Random;

Random random = new Random();
int a = random.nextInt(100); 		//0-100随机数

int randomnum = (int)Math.random()*100 + 1;		//生成1-100之间的随机数

chapter07 类与对象

属性

示例:

class Cat{
			String name;
			String color;
			int age;
		}

		Cat	cat1 = new Cat();
		cat1.name = "hhh";
		cat1.color = "yellow";
		cat1.age = 18;

方法

调用和定义示例:

public class Method01 {
	public static void main(String[] args){

		Person p1 = new Person();
		p1.speak();
		p1.cal01(1000);

	}
}

class Person{
	String name;
	int age;

	public void speak(){
		System.out.println("喵喵喵");
	}

	public void cal01(int n){
		int sum = 0;
		for(int i = 1 ; i <= n ; i++){
			sum += i;
		}
		System.out.println(sum);
	}
}

类数组

例如:

Person[] person = new Person[3];
person[0] = new Person("jack" ,29 ,"teacher");
person[1] = new Person("marry" ,16 ,"student");
person[2] = new Person("harry" ,18 ,"boy");

参数传递机制

parameter n.参数

  • 区分值传递和引用传递

    class Person{
    	String name;
    	int age;
    	}
    
    class B{
    	public void test01(Person p){
    		p = null;			//此时不会对原Person p造成影响,而是新开辟的test01栈中的p指向null		
    	}
    }
    

chapter08 递归

汉诺塔示例:

代码演示:

public class hanoiTower{
	public static void main(String[] args){
		Tower tower = new Tower();
		tower.move(5 , 'A' , 'B' , 'C');
	}
}

class Tower{
	public void move(int num, char a,char b,char c){
		if(num == 1){
			System.out.println(a  + "->" + c);
		}else{
			move(num - 1 ,a , c ,b);
			System.out.println(a + "->" + c);
			move(num - 1 , b ,c ,a);
		}
	}
}

八皇后问题:

代码演示:

public class EightQueen{
	static char map[][] = new char[8][8];
	static boolean col[] = new boolean[8];
	static boolean row[] = new boolean[8];
	static boolean dg[] = new boolean[20];
	static boolean udg[] = new boolean[20];
	static void find(int y){
		if(y == 8){
			for(int i = 0 ;i < 8;i++){
				for(int j = 0 ;j < 8;j ++){
					System.out.print(map[i][j]);
				}
				System.out.println();
			}
			System.out.println();
			return ;
		}else{
			for(int i = 0 ;i < 8 ; i++){
				if(!col[i] && !row[i] && !dg[y - i + 8] && !udg[i +y] ){
					map[y][i] = 'Q';
					col[i] = true;
					row[i] = true;
					udg[y + i] = true;
					dg[y - i + 8] = true;
					find(y + 1);
					map[y][i] = '.';
					col[i] = false;
					row[i] = false;
					udg[y + i] = false;
					dg[y - i + 8] = false;
				}
			}
		}
	}

	public static void main(String[] args){
 	for(int i = 0 ;i < 8; i++){
 		for(int j = 0; j< 8; j++){
 			map[i][j] = '.';
 		}
 	}
 	Queen queen = new Queen();
 	queen.find(0);
	}
}
//参考acwing详解

细节要点:

  • 清楚思路
  • 只管当前一步做什么,不要试图想清楚递归后在做什么

chapter09方法重载

  • 介绍
    • java中允许同一个类中,多个同名方法的存在,但要求形参列表不一致,比如System.out.println();
  • 重载的好处
    • 1)减轻起名的麻烦
    • 2)减轻记名的麻烦

重载示例:

public class OverLoad{
	public static void main(String[] args){
		myCalculator calculator = new myCalculator();
		int res1 = calculator.Calculator(1,5);
		double res2 = calculator.Calculator(2.45,3);
		System.out.println(res1);
		System.out.println(res2);
	}
}

class myCalculator{
	public int Calculator(int a,int b){
		return a + b;
	}
	public double Calculator(double a,double b){
		return a + b;
	}
}

可变参数

对功能相同和方法名相同的方法可以使用如下方法

public class var{
	public static void main(String[] args){
		varparameter temp = new varparameter();
		int res = 0;
		res = temp.getsum(1,2,3,4,5,6);
		System.out.println(res);

	}
}

class varparameter{
	public int getsum(int...nums){
		int sum = 0;
		for(int i = 0 ; i < nums.length ; i++){
			sum += nums[i];
		}
		return sum;
	}
}

注:上述代码中,类名var不可用Varparameter或者VarParameter代替,原因不详。

细节:
  • 允许可变参数与基本类型参数放在同一个参数列表,但是可变参数必须放在最后
  • 不允许多个可变参数在同一参数列表

作用域

1、主要的变量就是属性(成员变量)和局部变量

2、局部变量一般指成员方法中定义的变量,不可使用修饰符

3、全局变量(属性)可以不赋值使用,因为有初始值。而局部变量必须赋值后使用,无默认值。可以加修饰符,如static

构造器

public class constructor01{
	public static void main(String[] args){

		Person p1 = new Person(10 , "xiaoming");
		Person p2 = new Person("abc");
		System.out.println(p1.age + " " +  p1.name);
		System.out.println(p2.name);

	}
}
 class Person{
 	int age;
 	String name;
 	public Person(int pAge ,String pName){
 		age = pAge;
 		name = pName;
 	}
 	public Person(String pName){
 		name = pName;
 	}
 }


  • 用于属性的初始化
  • 程序员没有定义构造器时,系统默认构造一个无参构造器如:Person() {};

注:

javap对class文件反编译

this关键字

简单说:调用那个对象this就是代表那个对象

this(参数列表) 用于调用本类的构造器

chapter10 包

基本语法

package com.ending
//package 关键字,表示打包
//com.ending 表示包名
   
import java.util.*		//引入该包下的所有类

命名规则:

com.公司名.项目名.模块名

细节:

  • 要导入不同包中的同名类时,只能导入一个,另一个必须写详细包名

访问修饰符

  • public
    • 公开级别,对外公开
  • protected
    • 受保护级别,只对子类及同一个包中的类公开
  • 默认级别
    • 无修饰符,向同一个包的类公开
  • private
    • 只有类本身可以访问,不对外公开

访问权限

本类同包子类不同包
public
protected×
默认××
peivate×××

封装

  • 将set和get写在构造器中,可以保证安全并且验证数据
class Person{
    public  String name;
    private int age;
    private double salary;

    public Person() {
    }

    public Person(String name, int age, double salary) {
        this.setAge(age);
        this.setName(name);
        this.setSalary(salary);

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        if(name.length() >= 2 && name.length() <= 6 ) {
            this.name = name;
        }else this.name = "默认用户";
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if(age >= 1 && age <= 120) {
            this.age = age;
        }else {
            this.age = -1;
        }
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        if(salary >= 0) {
            this.salary = salary;
        }else this.salary = -1;
    }
}

继承

继承可以解决代码复用,当多个类中重复出现摸个属性时,可从中抽象出父类,子类 不需要重复定义,只需要extends继承。

基本语法

  • 子类extends父类
  • 子类自动拥有父类的属性和方法
  • 父类又被叫做超类和基类
  • 子类又叫派生类

细节

  • 子类继承了父类的所有属性和方法,但是私有属性不能被子类访问,需要公共方法访问
  • 子类必须调用父类的构造器,完成父类的初始化,默认使用super()调用父类的无参构造器
  • 需要指定调用父类的哪一个构造器时,需要显式地调用:super(参数列表);super使用时需要放在构造器的第一行且super只能在构造器中使用
  • this() 和super()不可共存,只能出现其中一个
  • 所有类都是object的子类
  • 父类构造器的调用不仅限于父类,将一直追溯到object类(顶级父类)
  • 子类最多继承一个父类,如果过要求c继承b和a的属性,应该先让b继承c,a再继承b
  • 不可滥用继承,必须满足is -a的关系

super

  • super代表父类的应用,用于调用父类的属性和方法

基本语法

  • 访问父类的属性,但不能访问父类的private属性
  • 不能访问父类private方法
  • 访问父类的构造器,只能放在构造器中,且只能写在构造器的第一条,只能出现一句,且不能和this同是出现

细节

  • 使用super和this可以使方法和属性各司其职
  • 当父类和子类中有相同属性和方法时,为了访问父类,就必须使用super
  • super访问不仅限于直接父类,当多个父类拥有同名属性或方法时,super采用就近原则

重写/覆盖(override)

子类中的某个方法与父类中的方法名称,返回类型,参数一眼,那么我们就称子类的方法覆盖了父类的方法

  • 子类不能缩小父类方法的权限

多态

方法或对象具有多种形态。基于封装和继承

对象的多态

  • 一个对象的编译类型和运行类型可以不一致
  • 编译类型在定义对象时就确定了,不可更改
  • 运行类型是可以变化的
  • 编译类型在 = 左边;运行类型在 = 右边;例如Animal animal = new Dog();此时 编译类型是Animal,运行类型是Dog
    • 代码运行时,取决于运行类型
    • 运行类型可根据需要来变更
  • 访问属性看编译类型
  • 访问方法,从运行类型开始向上查找

动态绑定机制

  • 当调用方法时,该方法会和运行类型绑定
  • 调用对象属性时,没有动态绑定机制,哪里声明,哪里使用

object类详解

== 与 equals对比

  • == 是比较运算符

    • 可判断基本类型与引用类型
    • 判断基本类型时,用于判断值是否相等
    • 判断引用类型时,判断地址是否相等,即判断是否为同一对象
  • equals用于对比两串字符串是否相等

hashCode

  • 提高具有哈希结构的容器的效率
  • 如果引用的两个相同对象则哈希值一样
  • 如果指向的是不同对象,则哈希值不一样
  • 哈希值主要根据地址号来计算,但不等价于地址

ToString

用于返回全类名 + @ +哈希值得16进制数

//Object中ToString的源码
public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

一般toString用于返回对象的所有属性

重写toString方法

class Monster{
    private String name;
    private int sal;

    public Monster(String name, int sal) {
        this.name = name;
        this.sal = sal;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getSal() {
        return sal;
    }

    public void setSal(int sal) {
        this.sal = sal;
    }

    @Override
    public String toString() {
        return "Monster{" +
                "name='" + name + '\'' +
                ", sal=" + sal +
                '}';
    }
}
System.out.println(monster);
// 这个语句默认是调用ToString
//与下面语句等价
System.out.println(monster.toString());

Date类

使用方法

Date date = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); 	 //格式转换
System.out.println(sdf.format(date));								//转换格式之后输出

第二阶段

类变量

也叫静态变量/静态属性,是该类所有对象公用的变量.

  • 定义语法

    • 修饰符 + static + 数据类型 + 变量名 或者 static+ 修饰符 + 数据类型 + 变量名 两种写法
  • 访问形式

    • 类名.变量名 或者 对象名.变量名 (一般使用类名.变量名的方法)

类方法

也加静态方法

语法规则: 修饰符 + static + 返回数据类型 + 方法名 +(参数列表) { };

代码块

用于当多个构造器中代码冗余时,使代码简洁高效。是构造器的一种补充机制,提高代码的复用性

class test{
    private String name;
    private double age;

    {
        System.out.println("代码块被调用");
    }

    public test(String name) {
        this.name = name;
    }

    public test(String name, double age) {
        this.name = name;
        this.age = age;
    }
}

上述实例中,两个构造器均调用代码块内容

代码块细节

  • static代码块也叫做静态代码块,作用是对类的初始化,而且随着类的加载而执行,并且只会执行一次。如果是普通代码块,每创建一次对象,就执行

  • 类什么时候被加载

    • 创建对象实例时(new)
    • 创建子对象实例时,父类会被加载
    • 使用类的静态成员时
public class test001 {
    public static void main(String[] args) {

        test test1 = new test();
        test test2 = new test();


    }
}

class test{
    static {
        System.out.println("代码块被执行");
    }
}

//此时test中的代码块只被执行一次,因为static代码块只有类被加载时才执行.且只执行一次
//区别于普通代码块,普通代码块每创建一个对象实例,就会执行一次
  • 普通代码块,在加载时会被隐式调用,创建一次,调用一次.如果只是使用类的静态成员,普通代码块不会被执行.(可以将普通代码块看作是构造器的补充,因此只在new一个对象时才会被调用)

单例设计模式

什么是单例模式?

单例(单个实例)

1、所谓的单例设计模式,就是采取一定的方法保证在整个软件的系统中,对某个类只能创建一个对象实例,并且该类只提供一个获取该实例的方法

2、单例模式有两种方式:1)饿汉式和2)懒汉式

饿汉式

步骤如下:

  • 构造器私有化(防止直接new)
  • 类的内部创建对象
  • 向外暴露一个静态的公共方法getInstance()
  • 代码实现
package com.ending.singleTon;

public class SingleTon01 {
    public static void main(String[] args) {
        Girlfriend instance = Girlfriend.getInstance();
        System.out.println(instance);
    }
}

class Girlfriend{
    private String name;

    private static Girlfriend gf = new Girlfriend("hhh");

    private Girlfriend(String name){
        this.name = name;
    }

    static Girlfriend getInstance(){
        return gf;
    }
}

懒汉式

只在调用是创建对象,第二次调用时已经创建所以返回第一次创建的对象,不会造成资源的浪费

package com.ending.singleTon;

public class SingleTon02 {
    public static void main(String[] args) {
        Cat instance = Cat.getInstance();
        System.out.println(instance);
    }
}

class Cat{
    private String name;
    public static int n = 100;
    
    private static Cat cat; //此时cat为null
    
    private Cat(String name) {
        this.name = name;
    }
    static Cat getInstance(){
        if(cat == null){
            Cat cat = new Cat("hhhh");
        }
        return cat;
    }
}

二者对比

  • 两者最大的区别在于创建对象的时机不同,饿汉在加载对象时就创建,懒汉在使用时才加载
  • 懒汉式存在线程安全问题
  • 饿汉式存在资源浪费的可能。如果一个对象创建了而没有被使用,那么资源被浪费。
  • 在javaSE标准类中,java.lang.Runtime就是典型的单例模式

final

final可以用于修饰类,属性,方法,局部变量

final修饰的属性一般被叫做常量,用XXX_XXX_XXX命名

使用场景

  • 当一个类不允许被继承时,用final修饰该类
  • 当不允许父类的某个方法被子类重写时
  • 当不允许某个属性被修改时
  • 当不允许局部变量被修改时
final class A {
    public final int n = 100;
}//此时A不允许被继承

class B{
    public final void Bmethod(){
        System.out.println("B方法被使用");
    }
}//此时Bmethod不允许被子类重写覆盖

class C{
    public final int n = 100;
    public void  Cmethod(){
        final int x = 1000;
    }
}//此时n不允许被修改,且x不允许被修改

final细节

  • final修饰的属性,必须赋初值,并且不允许被修改

    • 非静态属性,可以在定义时、构造器、代码块中赋值
    • 静态属性,只能在定义时,和静态代码块中赋初值
  • final类不可被继承,但是可以实例化

  • 一般来说,一个类如果已经是final类对了,就没有必要再将方法修饰成final方法因为此时该类已经不能被继承,所以也就不允许被重写

  • final不能修饰构造器

  • final往往与static搭配使用,效率更高,不会导致类被加载,底层编译器做了优化处理

  • 包装类(Integer、Double、Float、Boolean、String等)是final类

抽象类

抽象类介绍

  • 用abstract关键字来修饰一个类时,这个类就叫抽象类
  • 用abstract关键字修饰一个方法时,这个方法就是抽象方法,该方法没有方法体
  • 抽象类的价值更多是在于设计,是设计者设计好后,让子类继承并实现抽象类
  • 考官爱考,在框架和设计模式使用比较多
abstract class Animal{
    public abstract void eat();
}

细节

  • 抽象类不能被实例化
  • 抽象类不一定要包含abstract方法
  • 一旦类中包含abstract方法,该类只能为抽象类
  • abstract只能修饰类和方法,不能用来修饰属性和其他
  • 抽象类的本质还是类,可以有任意成员,比如构造器,非抽象方法,静态属性等
  • 抽象方法不能有方法主体
  • 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它也定义为抽象类
  • 抽象方法不能使用private,final,static来修饰因为这些修饰符本身会影响子类对该方法的重写

抽象类应用

模板设计模式

接口

基本介绍:接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,再根据具体情况把这些方法写出来

public class Interface001 {
    public static void main(String[] args) {
        BBB bbb = new BBB();
        bbb.hi();
    }
}

interface InterfaceAAA{
    public void hi();
}

class BBB implements InterfaceAAA{
    public void hi(){
        System.out.println("hi!!!");
    }
}

接口细节

  • 接口不能被实例化

  • 接口中所有方法都是public,接口中抽象方法,可以不用abstract修饰例如:void aaa() {}实际上是abstract void aaa();

  • IDEA中写接口中的全部方法可以使用Alt+Enter来自动补全

  • abstract类可以不实现接口中的方法

  • 一个类可以实现多个接口,并且要实现所有接口中的方法

  • 接口可以继承其他接口,但是接口不能继承其他类

  • 接口中的属性都是 final public static属性的

  • 接口访问形式 接口名XXX.属性

  • 接口的修饰符,和类一样,只能是public和默认

  • 当一个类实现某个接口时,允许该类直接访问接口中的属性

接口多态性

  • 多态参数
public class Interface001 {
    public static void main(String[] args) {
        a a1 = new a();
        b b1 = new b();
        c c1 = new c();
        c1.test(a1);
        c1.test(b1);  		//此时体现多态
    }
}

interface InterfaceAAA{
    public void hi();
}

class a implements InterfaceAAA{
    @Override
    public void hi() {
        System.out.println("AAA'hi");
    }
}

class b implements InterfaceAAA{
    @Override
    public void hi(){
        System.out.println("hi");
    }
}

class c{
    public void test(InterfaceAAA A){
        A.hi();
    }
}

如上例,c.test(),可以接收a,b两个对象,即可接收实现了同一接口的对象

  • 多态数组

接口虽不能被实例化,但是可以创建数组。

InterfaceAAA[] interfaceAAAS = new InterfaceAAA[3];
  • 接口存在多态传递现象

内部类

在一个外部类中嵌套一个类,叫做内部类,内部类的最大优点是可以直接访问私有属性,并且可以体现类与类之间的包含关系。

局部内部类

说明:局部内部类时定义在外部类的局部位置,比如方法中,并且有类名。

  • 内部类可以直接访问外部类的所有成员,包括私有属性
  • 不能添加修饰符,因为他的地位就是一个局部变量,局部变量是不能使用修饰符的,但是可以添加final,因为局部变量也可以添加final
  • 作用域:仅仅在定义他的方法或者代码块中。
  • 局部内部类访问外部成员,直接访问即可
  • 外部类访问局部内部类的成员,访问方式:先创建对象,再访问(注意:必须是在作用域内)
  • 如果外部类成员名和内部类成员名重复时,默认采用就近原则,如果想访问外部类的成员,需采用(外部类名.this.成员名的方式)

记住:局部内部类定义在方法/或者代码块中,作用域在方法体或者代码块中,其本质任然是一个类

public class InterClass01 {
    public static void main(String[] args) {
        outer outer001 = new outer(200);
        outer001.f1();
    }
}

class outer{
    private int n = 100;

    public outer(int n) {
        this.n = n;
    }

    {
        System.out.println("m1()");
    }
    public void f1(){
        class inner{
            int n2 = 20;

            public void f2() {
                System.out.println(n);
            }
        }

        inner inner001 = new inner();
        inner001.f2();
    }

}

匿名内部类

public class InnerClassExercise {
    public static void main(String[] args) {
        f1(new IA() {
            @Override
            public void show() {
                System.out.println("这是匿名内部类的使用演示");
            }
        });
    }

    public static void f1(IA ia) {
        ia.show();
    }
}

interface IA{
    void show();
}

成员内部类

  • 定义在成员位置的内部类,而不是在方法体中的(与匿名 内部类区分)
  • 可以访问外部类的所有属性,包括私有属性
  • 内部类作用范围:和外部类的其他成员一样,为整个类体,在外部类的成员方法构建一个内部类实体,再调佣方法
  • 其他外部类访问内部成员类:把内部类当做外部类的一个属性,如Outer.Inner inner = Outer.new Inner();或者在外部类中专门写一个方法用于返回内部类,如下演示
public class InnerClassTest01 {
    public static void main(String[] args) {
        outer01 outer = new outer01();
        outer.f2();
    }
}

class outer01{
    private int n1 = 1000;
    public void f1(){
        System.out.println("hi");
    }

    class inner01{
        public void f2(){
            System.out.println("访问外部类测试outer = " + n1);
        }
    }

    public void f2(){
        inner01 inner = new inner01();
        inner.f2();
    }
    
    //返回内部类
    public inner01 getinner(){
        return new innner01();
    }
}

静态内部类

  • 定义为static的内部类成员

  • 定义在成员位置的类,本质还是一个成员,所以可以加private,public等修饰符

  • 只能访问外部类中的静态属性,而不能访问非静态属性

  • 其他外部类也可以用类名访问静态内部类,但是必须满足访问权限的限制,在静态内部类中加private修饰,不可被其他外部类访问

public class InnerClassTest01 {
    public static void main(String[] args) {
        outer01 outer = new outer01();
        outer.f2();

    }
}

class outer01{
    private static int n1 = 1000;
    
    static class inner01{
        public void f2(){
            System.out.println("访问外部类静态属性测试outer = " + n1);
        }
    }

    public void f2(){
        inner01 inner = new inner01();
        inner.f2();
    }
}

枚举和注解

自定义实现枚举

public class Enumeration01 {
    public static void main(String[] args) {
        System.out.println(Season.AUTUMN);
        System.out.println(Season.SPRING);
        System.out.println(Season.SUMMER);
        System.out.println(Season.WINTER);
    }
}

class Season{
    private String name;
    private String describe;

    public static final Season SPRING = new Season("spring","温暖");
    public static final Season SUMMER = new Season("summer","炎热");
    public static final Season AUTUMN = new Season("autumn","凉爽");
    public static final Season WINTER = new Season("winter","寒冷");


    private Season(String name, String describe) {
        this.name = name;
        this.describe = describe;
    }

    public String getName() {
        return name;
    }

    public String getDescribe() {
        return describe;
    }

    @Override
    public String toString() {
        return "Season{" +
                "name='" + name + '\'' +
                ", describe='" + describe + '\'' +
                '}';
    }
}

enum关键字实现枚举

  • 定义常量对象必须写在最前面
  • 使用enum类开发时,默认会继承enum类,并且是final类
  • 使用无参构造器时,括号和参数列表均可省略
public class Enumeration02 {
    public static void main(String[] args) {
        System.out.println(Season02.SPRING);
        System.out.println(Season02.SUMMER);
    }
}

enum Season02{
    SPRING("春天","温暖"),SUMMER("夏天","炎热");
    //调用构造器

    private String name;
    private String desc;

    Season02(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }

    public String getName() {
        return name;
    }

    public String getDesc() {
        return desc;
    }

    @Override
    public String toString() {
        return "Season{" +
                "name='" + name + '\'' +
                ", desc='" + desc + '\'' +
                '}';
    }
}

  • 本质就是ToString
public class Enumeration03 {
    public static void main(String[] args) {
        System.out.println(Gender.BOY);
    }
}

enum Gender{
    BOY,GIRL;
    //相当于调用无参构造器
}

enum成员方法

  • name(); 输出枚举对象的名称

  • ordinal() 输出该枚举对象的编号

  • values() 方法返回一个枚举变量的数组详见下方代码

  • valueof() 方法将一段字符串与枚举对象进行比对,并返回枚举对象,比对失败则报错。

  • compareTo() 将两个枚举对象的编号进行对比,并且返回编号差值

public class Enumeration02 {
    public static void main(String[] args) {
        Season02 spring = Season02.SPRING;
        System.out.println(spring.name());
        System.out.println(spring.ordinal());
        Season02 values[] = Season02.values();
        for(Season02 season : values){
            System.out.println(season);
        }
        Season02 summer = Season02.valueOf("SUMMER");
        System.out.println(summer);
        System.out.println(Season02.SPRING.compareTo(Season02.SUMMER));
    }
}

enum Season02{
    SPRING("春天","温暖"),SUMMER("夏天","炎热");

    private String name;
    private String desc;

    Season02(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }

    public String getName() {
        return name;
    }

    public String getDesc() {
        return desc;
    }

    @Override
    public String toString() {
        return "Season{" +
                "name='" + name + '\'' +
                ", desc='" + desc + '\'' +
                '}';
    }
}

enum细节

  • enum类不可继承其他类:在底层源码中,enum类已经继承了类(隐式继承),如下反编译源码

  • enum类本质还是一个类,可以实现接口

注解

override

  • 在程序中标明@override,编译器会检查该方法是否重写
  • 只能用于方法标注

deprecated

  • 用于表示某个程序元素已过时
  • 可以修饰方法,类,字段,包,参数等等
  • @deprecated的作用可以做到新旧版本的兼容和过渡

supresswarring

  • 用于抑制警告warring

元注解

章末作业

在这里插入图片描述

public class Homework001 {
    public static void main(String[] args) {
        Cellphone cellphone = new Cellphone();
        cellphone.workTest(new Caculate() {
            @Override
            public double work(double n1, double n2) {
                return n1*n2;
            }
        },10, 8);

    }
}

interface Caculate{
    public double work(double n1, double n2);
}

class Cellphone{
    public void workTest(Caculate caculate,double n1,double n2){
        double result = caculate.work(n1,n2);
        System.out.println("result = " + result);
    }
}

异常处理

运行时异常

  • NullPointerException 空指针异常
  • ArithmeticException 数学运算异常
  • ArrayIndexOutOfBoundsException 数组越界异常
  • ClassCastException 类型转换异常
  • NumberFormatExceptio 数字格式不正确异常

throws细节

  • 编译异常必须处理,try-catch或者throws
  • 对于运行异常,程序中如果没有异常处理,默认是throws,最终将异常抛给JVM
  • 子类重写父类的方法,子类抛出的异常要么与父类一致,要么是父类异常的子类型
  • 在throws中,如果有try-catch,就相当于有异常处理,可以不必有throws
  • 一旦在try代码块中抛出异常,则在try块中抛出异常的语句后面的语句将不再被执行

自定义异常处理

public class CustomException {
    public static void main(String[] args) {
        int age = 20;
        if(!(age >= 18 && age <= 120)){
            throw new AgeException("年龄异常");
        }
        System.out.println("运行中");
    }
}

class AgeException extends RuntimeException{
    public AgeException(String message) {
        super(message);
    }
}

课后习题

在这里插入图片描述

public class HomeWork001 {
    public static void main(String[] args) {
        int length = args.length;

        try {
            if(length != 2){
                throw new ArrayIndexOutOfBoundsException("参数个数不正确");
            }
            int n1 = Integer.parseInt(args[0]);
            int n2 = Integer.parseInt(args[1]);
            double res = cal(n1,n2);

            System.out.println("res = " + res);

        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println(e.getMessage());;
        } catch(NumberFormatException e){
            System.out.println("参数格式不正确");
        }catch(ArithmeticException e){
            System.out.println("参数除0异常");
        }

        System.out.println("程序运行结束");

    }
    public static  double cal(int n1,int n2){
        return (double)n1/n2;
    }
}

常用类

String

集合

迭代器

 List list = new ArrayList();
 list.add(10);
 list.add("huhu");
 list.add(45687);

Iterator iterator = list.iterator();
while (iterator.hasNext()) {		//IDEA创建while循环快捷键itit
    Object next =  iterator.next();
    System.out.println(next);
}

增强for循环

int nums[] = {1,2,3,4,5,6};		//底层还是迭代器
        for(int i : nums){
            System.out.println(i);
        }

List接口

在这里插入图片描述

set接口

也为collection的子接口,方法与collection一致

  • 无序
  • 不允许重复
  • 可以添加一个null
  • 取出的数据不是输入顺序,但是每次输出都是一个固定的顺序

遍历形式

可以使用迭代器增强for循环其他普通方法

HashSet

是set接口的实现类

  • 实现了Set接口
  • 实际上是HashMap
  • 不保证存放数据顺序和取出顺序一致,取决于hash后的索引

HashSet底层机制说明

  • 底层是HashMap
  • 添加一个元素时,先得到hash值,再转换成索引值。
  • 找到存储数据表table,看这个索引位置是否已经存放有元素
  • 如果有,调用equals方法进行比较,如果相同,放弃添加。如果不同,则添加到最后。
  • 在java8中,如果一条链表的元素个数到达TREEILY_THRESHOLD(默认是8)并且table的大小>= MIN_TREEIFY_CAPACITY(默认是64),就会进行树化(红黑树)。

Map接口(JDK8)

  • 存放键值对(映射)数据(key-value)

  • key和value可以任意值,被封装到HashMap$Node对象中

  • Map中的key不允许重复,原因是存储下标通过key计算得到(重复时,前一个会被替换)

  • Map中的value可以重复

  • key和value都可以为null,但是key为null只能有一个,value不限

  • key和value存在一一对应的关系,可以通过key来找到value

总结

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值