JavaSE学习笔记 Day14

JavaSE学习笔记 Day14

个人整理非商业用途,欢迎探讨与指正!!
« 上一篇


文章目录

  • JavaSE学习笔记 Day14
    • ···
    • 十二、内部类
      • 12.1成员内部类
      • 12.2静态内部类
      • 12.3局部内部类
      • 12.4匿名内部类
      • 12.5内部类的应用
      • 12.6内部类中的this
      • 12.7内部类的好处
    • 十三、常用工具类
      • 13.1Object类
        • 13.1.1概念
        • 13.1.2Object类中的常用方法


···

十二、内部类

定义在一个类的内部,一个类中又有一个类,被称为内部类(InnerClass),外部的称之外部类(OuterClass)
内部类的特点:
 可以访问到外部类的所有成员,包括私有成员,不会破坏封装特性
 内部类同样会生成对应的字节码文件(.class),名字:外部类$内部类名.class
外部类的特点:
 一个java文件中可以编写多个类,但最多只能有一个类由public修饰,称为主类,主类的名称必须和文件名一致
 建议:一个java文件中只编写一个类

内部类的分类:
 类的成员:属性,方法,构造方法,注解,注释,代码块,内部类(可以直接写在类中的)
 成员内部类,静态内部类,局部内部类,匿名内部类

12.1成员内部类

类似于成员变量(属性)
只能定义非静态的属性和方法
可以无条件的访问所有外部类的成员
创建对象的语法:
 内部类 对象名 = new 外部类().new 内部类();//需要导包
 外部类.内部类 对象名 = new 外部类().new 内部类();//不需要导包

package com.qf;

public class OuterClass01 {
//	定义外部类的成员
	String name;
	protected int age;
	private String hobby;
	static int num;
	public void abc() {
		
	}

//	定义成员内部类
	public class InnerClass01 {
//		定义属性
		int a;
		private int b;
		public int c;
		protected int d;
//		不能定义静态成员
//		static int e = 10;
//		定义方法
		public void show() {
//			调用自身
			System.out.println(a+":"+b+":"+"c"+"d");
			test();
//			调用外部类的
			System.out.println(name+":"+age+":"+hobby+":"+num);
			abc();
		}
//		静态方法不行
		/*public static void test() {
			
		}*/
		public void test() {
		
		}
	}
}

12.2静态内部类

使用static修饰内部类
静态内部类中可以属性方法,静态属性方法
只能访问外部类的静态成员

创建语法
 内部类 对象名 = new 外部类.内部类();

package com.qf;

public class OuterClass02 {
//	定义外部类的成员
	String name;
	protected int age;
	private String hobby;
	static int num;
	public void abc() {
		
	}
	public static void def() {
		
	}
//	定义成员内部类
	public static class InnerClass02 {
//		定义属性
		int a;
		private int b;
		public int c;
		protected int d;
//		能定义静态成员
		static int e = 10;
//		定义方法
		public void show() {
//			调用自身
			System.out.println(a+":"+b+":"+"c"+"d");
			test();
//			调用外部类的静态资源
			System.out.println(/*name+":"+age+":"+hobby+":"+*/num);
//			abc();
			def();
		}
//		静态方法
		public static void test() {
			
		}
		public void test1() {
			
		}
	}
}

12.3局部内部类

只能定义在方法内部
特点:
 定义非静态成员
 可以访问外部成员
 只能在方法内部创建对象

package com.qf;

public class OuterClass03 {
//	定义外部类的成员
	String name;
	protected int age;
	private String hobby;
	static int num;
	
	public void abc() {
		int m = 1;
//		局部内部类
		class InnerClass03{
			int a = 10;
//			不能静态成员
//			static int b = 10;
			public void a() {
				System.out.println(name);
				System.out.println(age);
				System.out.println(hobby);
				System.out.println(num);
				System.out.println(m);
				System.out.println(a);
			}
		}
//		局部内部类创建对象的方式
		InnerClass03 c03 = new InnerClass03();
		c03.a();
	}
	public static void def() {
		
	}
}

12.4匿名内部类

匿名内部类本身就是一个对象

语法:
 new 类/接口(){
  //内部类 重写父类的方法
 };

特点:
 本身就是一个对象
 匿名内部类中一般单独不定义属性和方法,因为没有意义
 匿名内部类的父类一般是抽象类或者是接口
 匿名内部类只能使用一次

public static void main(String[] args) {
    //		匿名内部类
    MyAbClass mc = new MyAbClass() {
        //			方法的重写
        @Override
        public void test() {
            System.out.println("我是匿名内部类中的");
        }
    };

    mc.test();
    //		匿名内部类
    MyInter mi = new MyInter() {

        @Override
        public void show() {
            // TODO Auto-generated method stub
            System.out.println("show()...");
        }

    };

    mi.show();
}

12.5内部类的应用

/**
 * @author volume
 * @version 1.0.0
 * 该接口判断一个数是否为奇数
 * */
//	函数式接口,接口中只有一个方法
public interface MyInter {
	
	/**
	 * @param num传入一个数 判断这个数是否为奇数
	 * @return boolean true是奇数 false偶数
	 * */
	boolean odd(int num);

}
/**
 * 
 * @author y1538
 *	调用接口的方法
 */
public class MyTest {
//	接口调用
	public static void check(int num,MyInter mi) {
//		多态
		boolean flag = mi.odd(num);
		
		System.out.println(flag?"奇数":"偶数");
	}
}
// 工具的调用者
public class Test01 {
//	测试环节
	public static void main(String[] args) {
//		参数1为需要被判断的内容 参数2为功能
		MyTest.check(12, new MyInter() {
			@Override
			public boolean odd(int num) {
				if(num % 2 == 1) {
					return true;
				}
				return false;
			}
		});
	}
}

12.6内部类中的this

this表示当前类的对象
 若调用外部类和内部类的重名属性或者方法时,需要使用this进行区分

package com.qf;

public class OuterClass04 {

	int a = 10;
	public void show() {
		System.out.println("嗨嗨嗨");
	}
//	内部类的命名符合类的命名,只要在当前类中不重名就行
	class InnerClass {
		int a = 20;
		public void show() {
			int a = 30;
			System.out.println(a);
//			当前内部类中的a
			System.out.println(this.a);
//			调用外部类的a
			System.out.println(OuterClass04.this.a);
			
			OuterClass04.this.show();
		}
	}
	
	public static void main(String[] args) {
		InnerClass ic = new OuterClass04().new InnerClass();
		ic.show();
	}
}

12.7内部类的好处

1.内部类可以更好的实现隐藏
 外部类,不能使用private和protected进行修饰,但内部类可以

public class Test04 {

//	使用内部类去实现一个接口,然后实现的对应的方法为当前类所用
	private class Inner implements MyInter{
		@Override
		public void show() {
			System.out.println("hello");
		}
	}
	
//	定义获取内部类的方法
	public Inner getInner() {
		return new Inner();
	}
	
	public void show() {
		getInner().show();
	}
}

2.无条件的访问外部类的成员
 私有属性和方法都能访问

3.可以帮助java完成类的多继承
 通过内部类完成的

public class Test05 extends Dog{

	public class Inner extends Cat{
		
	}
//	获取名字方法
	public String getName() {
		return new Inner().name;
	}
	public String getType() {
		return type;
	}
}

class Dog{
	String type;
}

class Cat{
	String name;
}

4.避免继承和实现时方法重名

package com.qf;

public class Test06 {

	class Inner01 extends A {
		@Override
		public void show() {
			
		}
	}
	class Inner02 implements B {
		@Override
		public void show() {
			
		}
	}
	public void inner01Show() {
		new Inner01().show();
	}
	public void inner02Show() {
		new Inner02().show();
	}
}

abstract class A {
	public abstract void show();
}
interface B {
	void show();
}

十三、常用工具类

API:Application Programming Interface
 应用程序接口
Java-API中包含了java中的所有内置类及其使用方式

13.1Object类

13.1.1概念

Object类是java中所有类的根。 每个类都有Object作为超类(父类,基类)。
所有对象(包括数组)都实现了这个类的方法。
位于继承数的最顶端
所有类都直接或者间接继承了Object类,Object类中方法可以被所有类直接访问
Object可以作为多态参数的存在

13.1.2Object类中的常用方法
getClass方法
public final<?> getClass()
    	返回此Object的运行时类。 
    	返回java中运行期的真实类型
package com.qf.test;

import java.util.Scanner;

public class Demo01 {

	public static void main(String[] args) {
		Animal dog = new Dog();
		
		Animal cat = new Cat();
//		使用比较运算符判断类型
		System.out.println(dog instanceof Dog);
		System.out.println(cat instanceof Cat);
//		所有的对象都可以调用
		System.out.println(dog.getClass());
		System.out.println(cat.getClass());
		
		Scanner input = new Scanner(System.in);
		System.out.println(input.getClass());
		
		System.out.println("hello".getClass());
	}
}

class Animal {
	
}

class Dog extends Animal{
	
}

class Cat extends Animal{
	
}

hashCode方法
public int hashCode()
 返回对象的十进制地址值(哈希码)
 hash值通过hash算法计算得到,通过对象地址和对象中的字符串进行计算得到
 若对相同则hash一致,否则不一致
该方法建议被重写,重写的目的是为了配合equals使用

public class Demo02 {

	public static void main(String[] args) {
		Pig p1 = new Pig();
		Pig p2 = new Pig();
		Pig p3 = p1;
		
		System.out.println(p1.hashCode());
		System.out.println(p2.hashCode());
		System.out.println(p3.hashCode());
		
		System.out.println(p1.hashCode() == p2.hashCode());
		System.out.println(p1.hashCode() == p3.hashCode());
	}
}

class Pig {
	
}

toString方法
public String toString()
 返回对象的字符串表示形式。
 默认为:getClass().getName() + ‘@’ + Integer.toHexString(hashCode())
  全限定名@十六进制的hash值
 在使用System.out时,默认调用toString方法,直接显示地址形式
 一般情况下,我们想输出对象的同时显示对象的基本信息,所以会选择重写toString方法

@Override
public String toString() {
    // TODO Auto-generated method stub
    return "Mouse (名字:"+name+",年龄:"+age+",牙齿:"+teeth+")";
}
package com.qf.test;

public class Demo03 {

	public static void main(String[] args) {
		int[] arr = new int[3];
		System.out.println(arr);
		System.out.println(arr.toString());
		
		Mouse mouse = new Mouse();
		mouse.setName("苏塔");
		mouse.setAge(20);
		mouse.setTeeth(16);
		System.out.println(mouse.toString());
		System.out.println(mouse);
//		String中的toString重写过了,大多数的类都重写了toString
		System.out.println("hello".toString());
	}
}

class Mouse {
	private String name;
	private int age;
	private double teeth;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public double getTeeth() {
		return teeth;
	}
	public void setTeeth(double teeth) {
		this.teeth = teeth;
	}
	
	@Override
	public String toString() {
		return "Mouse [name=" + name + ", age=" + age + ", teeth=" + teeth + "]";
	}
	
	/*@Override
	public String toString() {
		return "Mouse (名字:"+name+",年龄:"+age+",牙齿:"+teeth+")";
	}*/
		
}

equals方法
public boolean equals(Object obj)
默认是比较两个对象的地址的,底层使用的是==运算符
 ==运算符:
 1.比较两个基本类型的数值是否一致
 2.比较两个对象的地址是否一致

// object源码
public boolean equals(Object obj) {
    return (this == obj);
}

equals方法的重写:
 作用:比较两个对象的内容是否一致,添加到某种容器(集合)中会使用
 equals方法的重写一般是和hashCode一起的(同时重写或者同时不重写)
  认为对象地址一致了,那么他们的hashCode也需要一致

@Override
public int hashCode() {
    //		定义了一个final变量为31(可以是任意值,31的重复概率是最低)
    final int prime = 31;
    int result = 1;
    result = prime * result + ((name == null) ? 0 : name.hashCode());//结果+字符串的hash值
    result = prime * result + no;//数值就直接加在里面
    return result;
}
//	重写equals的意义:比较两个对象的内容是否一样
@Override
public boolean equals(Object obj) {
    //		判断是否为同一个对象
    if (this == obj)
        return true;
    //		参数为null
    if (obj == null)
        return false;
    //		判断两个类的类型,若两对象的类型不一致
    if (getClass() != obj.getClass())
        return false;
    //		将参数转换为对应的类型的对象(向下造型)
    Person other = (Person) obj;
    //		按照各个位置进行值的比较
    if (name == null) {//两个字符串都是否为空
        if (other.name != null)
            return false;
    } else if (!name.equals(other.name))//比较的是字符串的内容是否一致
        return false;
    if (no != other.no)//比较基本类型的值是否一直
        return false;
    return true;
}

finlize方法
当垃圾回收机制检查到系统垃圾时,自动调用(jvm自动调用的)
可以使用System.gc()进行手动触发,需要等待cpu有空闲时间才会进行回收

public class LaJi {

	@Override
	protected void finalize() throws Throwable {
		System.out.println("垃圾回收机制开始运行");
//		不要删除
		super.finalize();
	}
	
	public static void main(String[] args) {
		LaJi lj = new LaJi();
//		手动的将对象标记为系统垃圾
		lj = null;
//		手动触发垃圾回收机制 jvm会自动的调用finalize()
		System.gc();
	}
}

你可能感兴趣的:(JavaSE,笔记,java)