包的概念_内部类_Java常用类_集合

1.包(package)

1.1 包的概念

包的位置:类上面,关键字package
包的真实意义:实际开发中对代码进行分层
一般命名:单词全部小写,而且是多级包,中间打点隔开,点就是分包(目录/文件夹)

1.2 带包的编译和运

手动方式:
1)先将某个.java文件编译
2)在当前目录下创建package后的目录 com.qf--->com文件夹下 qf文件夹
3)将(1)产生的字节码文件放在(2)qf文件夹里面
4)java  包名.类名

自动方式:
1)javac -d . java源文件 ----自动将包名以及包名下的类名.class产生出来
2)java 包名.类名  

2.内部类

在一个类class A中嵌套了另外一个类class B,我们就称class B为内部类

2.1 成员内部类

在外部类成员位置(类中方法外)的内部类

class Outer{//外部类

	class Inner{//成员内部类
	}
}

成员内部类的特点
成员内部类可以直接访问外部类的所有成员(包括私有)
外部类要访问内部类的成员,必须通过内部类的对象来访问

如何直接通过外部类来访问内部类的成员方法?
前提条件:成员内部类是非静态的
外部类名.内部类名  对象名 = new 外部类名().new 内部类名();
Outer.Inner inner = new Outer().new Inner();

成员内部类可以被private修饰,保护数据的安全性
成员内部类可以被static修饰,这个成员内部类的中的所有的方法,无论是静态的还是非静态的,访问外部类的成员必须只能访问静态的东西

外部类直接访问静态内部类的成员,可以将内部类看成外部类的成员
外部类名.内部类名 对象名 = new 外部类名().内部类名();

访问静态内部类的非静态方法:对象名.方法名();
访问静态内部类的静态方法:外部类名.内部类名.方法名();

2.2 局部内部类

在外部类方法中定义的内部类,称为局部内部类

class Outer{//外部类

	public void method(){//成员方法
	
		class Inner{//局部内部类
		}
	}
}

局部内部类的特点
可以直接访问外部类的所有成员(包括私有)

外部类如何直接访问内部类的成员?
在局部位置(方法中)创建内部类的对象,使用对象调用内部类的成员

public class Test{
	public static void main(String[] args){
		//创建外部类对象
		Outer outer = new Outer();
		//访问外部类方法
		outer.show();
	}
}

//外部类
class Outer{
	private int i = 10;
	//外部类的成员方法
	public void show(){
		int num = 20;
		//局部内部类
		class Inner{
			//成员方法
			public void method(){
				//访问外部类的私有成员属性
				System,out.println(i);
				//访问外部类的局部变量num
				System.out.println(num);
			}
		}
		//创建内部类对象
		Inner inner = new Inner();
		//调用内部类的成员方法
		inner.method();
	}
}

2.3 匿名内部类

匿名内部类:就是没有名字的内部类

格式:
抽象类或者接口的匿名内部类

new 类名或者接口名{
	重写方法(){
	}
};

适用场景:在方法的形式参数以及返回值是抽象类或者接口的情况下使用

匿名内部类的本质:就是继承了该类(抽象类)的子类对象或者是实现了该接口的子实现类对象

interface Love{
	void love();
}

//外部类
class Outer{
	public void method(){
		//没有使用匿名内部类之前
		/*
		class Inner{
			public void show(){
				System.out.println("show Inner...");
			}
		}
		
		//创建Inner对象
		Inner inner = new Inner();
		inner.show();
		*/
		//使用匿名内部类
		Love i = new Love(){
			@Override
			public void show(){
				System.out.println("show Love");
			}
		};
		i.show;
	}
}

//测试类
public class Test{
	public static void main(String[] args){
		//创建外部类对象
		Outer outer = new Outer();
		outer.method();
	}
}

匿名类的使用:形式参数为抽象类

//定义一个抽象类
abstract class Person{
	//抽象方法
	public abstract void work();
}
class PersonDemo{
	//方法形式参数为抽象类
	public void method(Person p){
		p.work();
	}
}

//测试类
public class Test{
	public void main(String[] args){
	
		PersonDemo pd = new PersonDemo();
		//使用匿名内部类
		pd.method(new Person(){
			@Override
			public void work(){
				System.out.println("我爱工作");
			}
		};)
	}
} 

匿名类的使用:返回值为接口

//定义一个接口
interface Cry{
	void cry();
}
class CryDemo{
	public Cry method(){
		return new Cry(){
			@Override
			public void cry(){
				System.out.println("小狗汪汪叫");
			}
		};
	}
}

//测试类
public class Test{
	public static void main(String[] args){
		//创建CryDemo类对象
		CryDemo cd = new CryDemo();
		//调用方法
		Cry c = cd.method();
		c.cry();
	}
}

3.Java常用类

3.1 Object类

所有类的父类,几乎所有的成员方法都要被任何子类重写

常用功能:

public String toString():本身含义:返回对象的字符串表现形式。
建议所有子类重写,返回的结果应该是一个简明扼要的信息表达式
而不是一堆地址值

public int hashcode():返回对象的哈希码值(可以理解为地址,但是不是
实际意义上的地址),每一个对象的哈希码值都是不同的

public boolean equals(Object o):比较两个对象是否相同,
建议所有子类重写该方法,否则,默认比较引用类型的地址值是否相同重写之后,
比较的是对象的内容是否相同

3.2 String类

特点:
String类:字符串是一个常量,采用创建字符串对象的方式,常量赋值—代表当前字符串的实例,对象一旦被创建,其值(常量池的地址)就不能被改变,除非重新去赋值
String类作为引用类型,当成为方法的形式参数,和基本类型的效果一致,形参的改变,不影响实参

String类的构造方法
String(char[] chs) :将字符数组构造成String
String(byte[] bytes):将字节数组构造成String

String类的常用功能

获取功能:
1public char charAt(int index):获取指定索引处的字符
2public String concat(String str):字符串拼接功能
3public boolean endsWith(String suffix):
判断此字符串是否以指定的字符串结尾
4)public boolean startsWith(String prefix〕:
判断此字符串是否以指定的字符串开头
5public boolean equals(Object anObject):
比较是两个字符串的内容是否相同
6public boolean equalsIgnoreCase(String anotherString) :
比较两个字符串内容是否相同,忽略大小写进行比较
7String subString(int beginIndex):
通过截取字符串,获取一个新的字符串(从指定位置截取,默认截取到末尾)
8String subString(int beginIndex, int endIndex):
通过截取字符串,获取一个新的字符串,
从指定位置开始,到指定位置(endIndex)结束
9int length():获取字符串长度
转换功能:
1char[] toCharArray() :String转换字符数组
2byte[] getBytes() :将字符串转换成字节数组
3String[] spilt(String regex):通过指定的分割符号,将字符串转换成字符串
数组
4public static String valueOf(int/double/long/....Object):可以将任何类
型转换String
5String toUpperCase() :转换成大写
6String toLowerCase():转换成小写
其他功能:
public int compareTo(String str):按照字典顺序进行比较两个字符串
方法解释:
将两个字符串转换为字符数组,获取两个字符数组的长度
Math.min(长度1,长度2)
定义一个统计变量
while(统计变量<最小长度){
	统计变量从0开始,依次比较两个字符数组的每一个字符值
	判断每一个字符值是否不相等
	如果不相等,则返回两个字符的ASCII码值相减的结果
}
循环结束,如果上面判断一直不成立
则返回长度1-长度2

3.3 StringBuffer类

StringBuffer:线程安全的可变的字符串缓冲区

常用构造方法
StringBuffer():空参构造,创建一个空的字符串缓冲区对象
StringBuffer(String str):
将指定的字符串存储在字符串缓冲区,将String类型转换成StringBuffer类型

StringBuffer常用功能:
1)public StringBuffer append(任意类型数据):
	添加任意类型数据到字符串缓冲区中,返回字符串缓冲区本身
2)public StringBuffer reverse():
	将字符串缓冲区字符序列反转
3)public StringBuffer insert(int offset, Object obj):
添加Object类型的参数到该字符序列中

3.4 String和StringBuffer的区别

String的特点:字符串常量,一旦创建,其值不改变,不支持可变的字符序列
StingBuffer:支持可变的字符序列,而且线程安全的---执行效率低,多线程会用,
单线程环境下用StringBuilder类

方法的形式参数:
String和基本类型效果一样,形参的改变不影响实参
StringBuffer:作为方法的形式参数,形参改变会影响实参

3.5 Integer类

自动拆装箱
基本数据类型—>对应的引用数据类型:“装箱”
引用数据类型—>对应的基本数据类型:“拆箱”

Integer类的构造方法

public Integer(int value):将int类型----Integer类型
public Integer(String s) :将数字字符串转换成Integer
字符串保存的必须是数字字符串

Integer内部缓存区
内部缓存区:Integer类的静态的成员内部类 IntegerCache
low和high的值:-128~127;
如果直接将int类型直接赋值给Integer,实际底层调用的是Integer.valueOf(int的值)
判断当前int类型的值是否在-128~127之间,如果在,直接从内部缓存区中的Integer[] cache中取得数据,并返回该值,如果超过这个范围,则重新创建对象new Integer(int类型的值)

3.6 Character类

构造方法

Character (char value):将一个char类型的值构造成一个Character类对象

常用方法

1)public static boolean isUpperCase(char ch)
	判断字符是否为大写字母字符
2)public static boolean isLowerCase(char ch)
	判断字符是否为小写字母字符
3)public static boolean isDigit(char ch)
	判断字符是否为数字字符

3.7 Date类

表示日期,可以精确到毫秒

构造方法

public Date():无参构造方法:创建日期对象,
获取当前系统时间的日期格式:包含星期 年份 月份 月中的日期。..
public Date(long date):创建日期对象,和1970年1月1日有关系

常用功能

public long getTime():获取时间的毫秒值

Date重点:日期文本格式和Date如何转换?

使用中间桥梁:DateFormat类 是一个抽象类,不能实例化,
jdk提供更具体的子类:SimpleDateFormat

构造方法
public SimpleDateFormat(String pattern)
yyyy:年 MM:月 dd:月中日期 HH:小时 mm:分钟 ss:秒

成员方法:
	Date---->String public String foramt(Date date) :格式化
    String--->Date: public Date parse(String dateStr) throws ParseException: 解析
    这个本身可能出现异常,如果解析的字符串的格式和 pattern参数的模式匹配,就出错了,解析失败!
//需求:键盘录入出生日期,计算来到这个世界多少天
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class Test {
    public static void main(String[] args) throws ParseException {
        //获取当前系统时间
        Date nowDate = new Date();

        //创建键盘录入对象
        Scanner sc = new Scanner(System.in);

        //提示用户输入并接收
        System.out.print("请输入出生年月日(yyyy-MM-dd):");
        String bornDate = sc.nextLine();

        //将bornDate日期文本转换为Date格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date birthDay = sdf.parse(bornDate);

        //获取出生日期的毫秒值
        long oldTime = birthDay.getTime();

        //获取当前日期的毫秒值
        long newTime = nowDate.getTime();

        //输出毫秒值
        System.out.println("出生日期的毫秒值为:" + newTime);
        System.out.println("当前日期的毫秒值为:" + oldTime);

        //计算差值,换算成天数
        long day = (newTime - oldTime) / 1000 / 60 / 60 / 24;

        //输出结果
        System.out.println("你来到这个世界已经" + day + "天了");
    }
}

3.8 Random类

随机数生成器

构造方法
Random():创建对象后,调用nextInt()/nextInt(int n):每次随机数不一样
public Random(long seed) :不推荐,调用nextInt()/nextInt(int n):每次随机数一样

成员方法
int nextInt():int类型的范围获取
int nextInt(int n):范围是[0 , n)

3.9 System类

常用功能
1)public static void exit(int status):
参数为0,退出Jvm(正常终止)(如果不为0 ,属于异常终止)
2)public static long currentTimeMillis():获取当前系统时间的毫秒值
3)public static void gc():手动开启垃圾回收器,回收没有更多引用的对象,
	会调用Object类的finaliza()方法
4)public static void arraycopy(Object src,  数据源(举例:原数组)
                          	 int srcPos,  原数组中某个位置
                             Object dest,  目的数据(目标数组)
                             int destPos,  目标数组的某个位置
                             int length  复制的长度   )

4. 集合

集合是个容器,特点:支持可变长度

4.1 Colleation集合

Collection接口:集合的顶层次的根接口,代表所有的单列集合,只能存储一种引用类型的集合

						Collection接口<引用类型>
			List子接口                             Set子接口
		实现类											实现类
		ArrayList										HashSet
		LinkedList										TreeSet
		Vector

常用方法:
boolean add(E e):在集合末尾添加元素
boolean contains(Object o):判断集合中是否有指定的元素
boolean remove(Object o):删除本集合中的o元素
void clean():清空本集合
boolean isEmpty():判断集合是否为空
int size():获取集合中的元素个数
Object[] toArray():返回一个包含本集合所有元素的数组
Iterator iterator():迭代器,集合专用的遍历方式

集合的专有遍历方式----“迭代器”

Iterator<E> iterator()
返回值是一个接口:
               Iterator:
                   Object next()返回迭代中的下一个元素。  (返回任意java类型)
                   boolean hasNext():判断功能:判断迭代器中是否下一个元素
                                   返回true,表示存在
                                   返回false,不存在!

4.2 List集合

List集合特点

(1)元素可以重复
(2)存储顺序和取出顺序一致(有序性)

List集合存储字符串,有几种方式遍历?
(1)使用Object[] toArray()方法,将对象转换为数组进行遍历
(2)使用迭代器 Iterator<E> iterator()进行遍历
特有方式:
(1)普通for()循环:使用int size()和E get(int index)方法进行遍历
(2)使用集合的列表迭代器ListIterator  listiterator()
		ListIterator:
              boolean hasNext():是否有下一个元素
              E next():获取下一个元素
(3)使用增强for:增强for是jdk5的新特性,为了代替迭代器的使用(简化代码书写)
		for(集合中存储的数据类型  变量名:集合对象或者数组对象){
			使用变量即可
		}

List集合常用的三个子实现类:ArrayList,LinkedList,Vector
三个子实现类的特点:

(1)ArrayList:底层数据结构是数组,查询快,添加删除比较慢;
	从线程的角度来考虑,ArrayList是不同步的,不安全的,但是效率比较高
	(在单线程程序中,只考虑效率)
	
(2)Vector:底层数据结构是数组,查询快,添加删除比较慢;
	从线程的角度来考虑,Vector是一个同步的,安全的集合,执行效率比较低
	如果在多线程的环境下,就必须使用Vector集合,因为要考虑安全性
	
(3)LinkedList:底层数据结构式链表,查询比较慢,因为每一次查询都需要从链表开头查询;
	添加和删除比较方便
	从线程的角度考虑,LinkedList是一个线程不安全的集合,不同步,效率比较高

List集合存储自定义对象去重

分析:
(1)首先创建一个List集合对象,往集合中添加自定义类型的对象
(2)创建一个新的List集合
(3)编译以前的集合,获取到每个元素,在新的集合中判断是否有以前集合的元素,如果没有,
	就将这个元素添加到新集合中
	使用boolean contains(Object o)方法判断
(4)最终遍历新集合
注意:必须在自定义类中重写equals()方法和hashCode()方法,
否则contains方法比较的是对象的地址值,而不是对象的内容
import java.util.ArrayList;
import java.util.List;

public class Exercise {
    public static void main(String[] args) {
        //创建List集合对象
        List<Student> list = new ArrayList<>();
        //添加元素
        list.add(new Student("张三", 18, '男'));
        list.add(new Student("张三", 18, '男'));
        list.add(new Student("李四", 17, '男'));
        list.add(new Student("小红", 17, '女'));
        list.add(new Student("小花", 18, '女'));
        list.add(new Student("小花", 16, '女'));
        list.add(new Student("小花", 16, '女'));
        for (Student s : list){
            System.out.println(s);
        }

        //创建一个新的集合
        List<Student> c = new ArrayList<>();
        //增强for遍历原集合
        for (Student s : list) {
            //判断新集合是否有当前元素,如果没有,就将当前元素添加到新集合中
            if (!c.contains(s)){
                c.add(s);
            }
        }
        System.out.println("--------去重后--------");
        for (Student s : c) {
            System.out.println(s);
        }

    }
}

//自定义学生类
class Student{
    private String name;
    private int age;
    private char gender;

    public Student(String name, int age, char gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public char getGender() {
        return gender;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                '}';
    }

    //重写equals方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && gender == student.gender && name.equals(student.name);
    }

    //重写hashCode方法
    @Override
    public int hashCode() {
        return Objects.hash(name, age, gender);
    }
}

代码运行结果
在这里插入图片描述

4.2.1 LinkedList

特点:底层数据结构是链表,特点:查询慢,添加删除快,是线程不安全的

特有功能
(1)public void addFirst():将指定元素添加到链表开头
(2)public void addLast():将指定元素添加到链表结尾
(3)public E removeFirst():删除第一个元素并返回
(4)public E removeLast():删除最后一个元素并返回
(5)public E getFirst():获取第一个元素
(6)public E getLast():获取最后一个元素
(7)public void push(E e):推送到链表开头
(8)public E pop():弹出最后一个元素

4.2.2 Vector

底层数据结构是数组,特点:查询快,添加删除比较慢
线程安全的类—同步的—执行效率比较低(多线程环境下使用安全性比较大的类)

特有功能:
(1)public void addElement(E obj):
	添加元素,如果E的数据类型确定了,就只能添加这一种类型的元素
(2)public Enumeration<E> element():获取组件(返回值是枚举接口---产生一系列元素)
        类似与Colleation集合的Iterator iterator()迭代器
        Enumeration枚举接口
            boolean hasMoreElement():判断是否有更多的元素
                            ---类型与Iterator迭代器里面的hasNext()
            E nextElement():获取下个元素
                            ---类似于Iterator迭代器中的next()
                            
(3)public E elementAt(int index):通过索引获取元素

4.3 Set集合

特点:保证元素唯一,而且不能保证迭代次序
唯一,无序性(元素不重复,不能保证顺序—哈希表(key-value键值对)完成的(桶状结构)

 为什么会保证元素唯一?HashSet依赖于Map<K,V>接口的子实现类HashMap<K,V>实现的
 HashSet的add()方法依赖于HashMap的put方法,间接依赖于Object类的equals和hashCode

特点的代码体现

import java.util.HashSet;
import java.util.Set;

public class HashSetDemo {
    public static void main(String[] args) {
        //创建HashSet对象
        Set<String> set = new HashSet<>();

        //添加元素
        set.add("java");
        set.add("java");
        set.add("hello");
        set.add("Hello");
        set.add("world");

        System.out.println(set);
    }
}

Set集合元素的唯一性和无序性

5. 权限修饰符

本类同包子类,同包其他类不同包子类不同包其他类
public
protected
默认
private

6.形式参数或者返回值为具体类,抽象类或者接口的问题

6.1 形式参数问题

1. 形参为具体类

方法的形参类型为具体类,那么传递的时候应该传递这个类的一个具体对象

2. 形参为抽象类

方法的形参类型为抽象类,那么传递的时候应该传递这个抽象类的子类对象

3. 形参为接口

方法的形参类型为接口,传递参数的时候应该传递这个接口的子实现类对象

6.2 返回值问题

1. 返回值为具体类

方法的返回值类型为具体类,应该返回当前类的一个具体对象

2. 形参为抽象类

方法的返回值类型为抽象类,应该返回该抽象类的子类对象

3. 形参为接口

方法的返回值类型为接口,应该返回该接口的子实现类对象

7.面试题

7.1 成员内部类面试题

/*
	看程序补全代码,在控制台输出30,20,10
*/
public class Test{
	public static void main(String[] args) {
		Outer.Inner oi = new Outer().new Inner();
		oi.method();
	}
}

class Outer{//外部类
	int num = 10;

	class Inner{//成员内部类
		int num = 20;
		
		//成员内部类的成员方法
		public void method() {
			int num = 30;
			//在下面补全代码
			System.out.println(num);
			System.out.println(this.num);
			System.out.println(new Outer().num);
		}
	}
}

7.2 局部内部类面试题

jdk版本7的版本,局部内部类访问的外部类的成员方法的局部变量,这个局
部变量有什么特点?为什么?

jdk7及以前版本:
		定义变量:int num = 20;//立即报错,变量需要用final修饰
jdk8已经优化
		定义变量:int num = 20;//不会报错
为什么?
	因为局部变量的生命周期是
	随之方法的调用而存在,随着方法的调用结束而消失,
	在代码中,show()方法调用完毕,num就应该被释放,
	但是,在show()方法中,创建了一个局部内部类的对象,
	对象中的成员方法在间接的使用外部类的局部变量,
	所以不能让num立即释放,
	所以用final修饰,让num变成了一个常量。

7.3 集合和数组有什么区别

(1) 长度的区别
	数组:长度固定
	集合:长度可变
(2)存储的数据类型的区别
	数组:既可以存储基本数据类型,也可以存储引用数据类型
    集合:只能存储引用数据类型
(3)存储元素的区别
	数组只能存储同一种类型的元素
    集合本质可以存储任意引用类型的元素(多种引用类型)
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值