java基础(类与对象、集合)

  • 类与对象
  • 类与对象中的栈和堆
  • 构造方法
  • this关键字
  • 面向对象三大特性
  • 封装性(private)
  • 继承性(extends)
  • 方法重写(@override)
  • 多态性
  • 向上转型(upcasting)
  • 向下转型(downcasting)
  • 简单工厂模式
  • final关键字
  • 抽象类
  • 接口
  • 集合
  • ArrayList
  • 泛型
  • LinkedList
  • Set集合
  • 哈希表
  • Map


类与对象

举例:
1.就拿英雄联盟或者王者荣耀来说
英雄这个统称我们叫做类
具体的哪个英雄我们称之为对象

2.做月饼
做月饼的模具我们可以称之为类
通过磨具做出来具体的月饼我们称之为对象

类和类中的对象都有一些共同的属性,对象是根据所在类的共同属性而做出来的

类是对象的模板,对象是类具体的一个实例

创建一个简单的类与对象:
类文件代码:

package OOPdemo;

public class Person {
	// Person类所拥有的属性
    String name;
    int age;
    // Person类所拥有的方法
    public void eat(){
        System.out.println("在吃饭");
    }
    public void study(){
        System.out.println("在学习");
    }
    public void sleep(String place){
        System.out.println("在"+place+"睡觉");
    }
}
package OOPdemo;

public class Test1 {
    public static void main(String[] args) {
    	// 创建一个zs的对象
        Person zs = new Person();
        // 给zs对象上绑定person类的属性
        zs.name = "张三";
        zs.age = 21;
        zs.eat();
        zs.study();
        zs.sleep("寝室");
    }
}

类与对象中的栈和堆

1.每个线程(调用一次main就会开启一个新的线程)会有单独的一个栈。每次调用方法,就会开启一个栈帧,方法结束以后栈帧弹出。先进后出。和垃圾回收机制没有关系。存放局部变量

2.堆内存中是共享的空间,不管多少线程,共享一块堆内存,对象中的内容都是存在堆内存中的。如果对象失去了指向,那么就会被垃圾回收。存放成员变量

构造方法

1.也叫做构造器
2.和类同名,不写返回值类型
3.完成对象的初始化操作
4.如果没有构造初始化方法,则系统会自动提供一个无参的构造方法

this关键字

this的作用:
1.每创建一个对象,都会产生一个this的引用变量,指向当前对象
2.在类的内部,可以通过this来访问类的成员

this的使用:
this.no = no;(调用成员变量,如果变量同名,则可以使用this来区分)
this(no, name);(调用构造方法,则需要放在方法内部的第一句)

面向对象三大特性

封装性(private)

访问权限修饰符:private、默认、protected、public
private:表示私有,只有自己类能够访问
默认:只有同一个包的类能够访问
protected:表示可以被同一个包的类和其他包的子类访问
public:表示可以被该项目的所有包中的类访问

类的属性的处理:
1.一般使用private访问权限
2.用封装的get、set方法来访问操作相关属性(注意:如果有传参的构造方法初始化传递的参数,则需要在构造方法中也使用set、get方法来对参数进行赋值)

类的处理:
1.类只能使用public和默认来进行修饰
2.默认:当前包
3.public:当前项目下的所有包

继承性(extends)

定义:继承可以让我们更加容易实现对类的扩展,比如说我们定义了动物类,那么哺乳动物就可以继承动物的公有属性或者方法(比如说都有名字、年龄、会说、会吃等等)

使用要点:
1.默认父类:Object
2.super:代表直接父类对象
3.this:指向对象本身
4.只有单继承
5.子类继承父类,可以得到父类的全部属性和方法,但不一定可以全部使用,因为可能会出现私有属性或方法

方法重写(@override)

背景:从父类继承下来的方法已经无法满足子类的需求了,这时我们可以考虑方法重写

public void introduce (){
	super.introduce() ; //通过super调用父类的方法,这里可以选择不调用父类方法,完全自己重写
	system.out.println (nickName) ;
}

注:
1.如果有修饰符final表示最后一个,则不能重写;如果是静态方法,则不能重写。
2.IDEA中alt+insert可以快速创建构造方法和set和get方法等等

多态性

多态指的是同一个方法调用,对象的不同会导致可能会有不同的行为,比如说,同样是吃饭,中国人是用筷子吃饭,而英国人使用刀叉吃饭

多态要点:
1.多态和成员变量无关,和重写的方法有关
2.无法调用子类特有的方法
3.多态的存在有3个必要条件(继承,方法的重写,父类引用指向子类对象)
4.父类引用指向子类对象后,用该父类调用子类重写的方法,此时多态就出现了

Programmer pro = new Chinese();//父类引用指向父类对象
pro.writeCode();
pro.eat();//多态,调用中国人的吃饭方法
向上转型(upcasting)
//引用数据类型的类型转换
Programmer pro = new Chinese();//此时是自动转换,向上转型,chinese向programer转型
pro.writeCode();//调用从父类继承的方法,结果是唯一的
pro.eat();//调用被子类重写的方法,结果是子类的结果
向下转型(downcasting)

将父类的引用变量转换成子类的类型,叫做向下转型,向下转型后就可以调用子类特有的方法。
1.需要进行强制转换
2.跟基本数据类型向下转换不同,基本数据类型强制向下转换相当于“做手术”。引用类型强制转换不能“做手术”,必须转化为真实的子类类型

//引用数据类型的类型转换
Programmer pro = new Chinese();
pro.eat();
//pro.playBoxing();***不能直接使用子类特有的方法
Chinese ch =(Chinese)pro; //向下强制转换
ch.playBoxing() ;   //此时可以调用子类特有的方法

注:在类的继承树关系上,必须要有上下级关系

简单工厂模式

工厂负责创建,使用者直接调用;
基本要求:
1.定义一个static方法,可以直接通过类名调用
2.传入一个字符串类型的参数,工厂根据参数创建相应的对象(子类产品)

final关键字

作用:
1.修饰变量:被修饰后不能被改变,一旦被赋值,就不能重新赋值
final a = 100;
2.修饰方法:不能被重写,但可以被重载
final void look(){}
3.修饰类:被修饰的类不能被继承
final class A{}

注意:
1.不能修饰构造方法
2.修饰基本数据类型,只能赋值一次
3.修饰引用数据类型时,比如:
final Cat cat = new Cat();
不能变的是cat这个对象的引用地址,其内部的属性还是可以发生改变的

抽象类

比如说我们创建动物类的时候,有时候不希望这个动物类不被new成一个实例对象,就可以在类之前加上一个abstract(抽象的),就可以防止被new出一个新Animal

Animal类

public abstract class Animal {
    private String name;
    private int age;
    // 无参构造方法
    public Animal() {
    }
    // 有参构造方法
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

主类

public static void main(String[] args) {
//        Animal an = new Animal();  会报错,因为Animal是抽象类
    }

扩充:抽象方法:
Animal类:

public abstract void look();/*{
        System.out.println("----动物在看----");
    }*/

特点:没有方法体,告诉子类必须给抽象方法具体的实现,否则会报错
Dog类:

public void look(){
        System.out.println("---animal look---");
    }

接口

背景:
比如说多种事物都有同样的功能,比如人和爬行动物都有吃的功能,但他们的父类都不是同一个,此时就可以使用接口来实现

定义:
1.接口定义的是一种规范,一组规则
2.接口中定义的全是全局静态final常量
3.接口不能new,也没有构造方法,不会自动继承类
4.接口中所有的方法都是抽象的
5.接口之间用的是继承(extends)
6.接口与类之间用的是实现(implements)实现接口中的规范
接口中定义一个常量:

public static final int age;
// 接口中下面这种的定义方式的性质其实就是上面这种
int age;

注:既有继承又有实现的话,先写继承extends再写实现implements

最后还有异常和常用类,做实际项目时都会接触到的,建议多敲代码,这两个就很好理解

集合

ArrayList

//        创建一个ArrayList对象
        ArrayList arr = new ArrayList();
//        向ArrayList中添加元素
        arr.add(80);//在末尾添加一个元素
        arr.add(69);//自动装箱
        arr.add(68);//集合的元素必须是对象类型
        arr.add(1, 100);//指定位置添加数据
//        获取ArrayList的数据
        System.out.println("---------------------------");
        System.out.println(arr);
        System.out.println(arr.size());//获取元素个数
        System.out.println(arr.get(1));//获取索引对应元素
//        遍历arr
        System.out.println("---------------------------");
//        1、
        for (int i = 0; i < arr.size(); i++) {
            int arrs = (int)arr.get(i);
            System.out.println(arrs);
        }
        System.out.println("-------------------------------");
//        2、使用迭代器遍历
        Iterator it = arr.iterator();
        while (it.hasNext()){
            int its = (int)it.next();
            System.out.println(its);
        }

缺点:
1.遍历得到的数据类型是对象,需要强制转换
2.添加字符串类型数据不安全

解决办法(**

泛型

**(jdk1.5))(数据安全,不需要强制转换):

//        创建一个ArrayList对象
        ArrayList<Integer> arr = new ArrayList<Integer>();
//        2、使用迭代器遍历
        Iterator<Integer> it = arr.iterator();

其他方法:

//        删除方法:
        arr.clear();//全部删除
        arr.remove(new Integer(80));//删除内容为80的元素
        arr.remove(1);//删除索引为1的元素

//        修改方法:
        arr.set(0,99);

LinkedList

和ArrayList使用方法基本相同
相对于ArrayList提供了更多的方法

不同的地方:
1.底层的存储结构发生改变
ArrayList:数组
LinkedList:双向链表

2.方法底层的实现(比如在指定位置添加元素)
ArrayList:后移元素 效率较低
LinkedList:修改前后节点指针 效率较高

使用哪种集合根据情况而定:
如果是添加删除元素 LinkedList
如果是按照索引查询元素 ArrayList

Set集合

Set <String>se = new <String>HashSet();
        se.add("HTML");
        se.add("CSS");
        se.add("Javascript");
        se.add("HTML");//不接受重复数据
        System.out.println(se.size());//3
        System.out.println(se.toString());//[CSS, Javascript, HTML]

HashSet:唯一、无序

Set <String>se = new <String>LinkedHashSet();
        se.add("HTML");
        se.add("CSS");
        se.add("Javascript");
        se.add("HTML");//不接受重复数据
        System.out.println(se.size());//3
        System.out.println(se.toString());//[HTML, CSS, Javascript]

LinkedHashSet:唯一、有序(添加顺序)

Set <String>se = new <String>TreeSet();
        se.add("HTML");
        se.add("CSS");
        se.add("Javascript");
        se.add("HTML");//不接受重复数据
        System.out.println(se.size());//3
        System.out.println(se.toString());//[CSS, HTML, Javascript]

TreeSet:唯一、有序(自然顺序)、红黑树(从小到大)

遍历方法(foreach、迭代)

//        两种遍历方法
//        1.foreach
        for (String ele:se
             ) {
            System.out.println(ele);
        }
//        2.迭代
        Iterator<String> it = se.iterator();
        while (it.hasNext()){
            String ele = it.next();
            System.out.println(ele);
        }

哈希表

哈希表中添加数据步骤:
1.计算哈希码
x=key.hashCode();
2.根据哈希码计算存储的位置
y=x%11;
3.存入指定的位置
情况一、如果是空链表:直接添加一个节点
情况二、如果不是空(数据不相同):调用equals进行比较,如果没有相同的内容,则添加到节点中
情况三、如果不是空(数据相同):调用equals进行比较,如果有相同的内容,则不再添加,确保了数据的唯一性

哈希表的查询和添加顺序是一样的

Map

特点:key唯一、无序

创建方法和Set类似,不过要注意的是使用泛型时要指定key和value的数据类型

添加数据用put方法

HashMap:

//创建一个map对象
        Map<String,String> map = new HashMap<String,String>();
        //向map对象中添加数据
        map.put("cn","China");
        map.put("jp","Japen");
//        查看数据
        System.out.println(map);//{jp=Japen, cn=China}
        System.out.println(map.size());//2

key:唯一、无序、HashSet特点
value:不唯一、无序

LinkedHashMap:

//创建一个map对象
        Map<String,String> map = new LinkedHashMap<String,String>();
        //向map对象中添加数据
        map.put("cn","China");
        map.put("jp","Japen");
//        查看数据
        System.out.println(map);//{cn=China, jp=Japen}
        System.out.println(map.size());//2

key:唯一、有序(添加顺序)、LinkedHashSet特点
value:不唯一、无序

TreeMap:
key:唯一、有序(自然顺序)、TreeSet特点、不能添加空元素
value:不唯一、无序

Map常用操作:
创建对象、添加数据、根据key查找数据
遍历:

//通历2∶得到所有的key-value组成的set,直接逼历Set 推荐使用
        Set<Map.Entry<String,String>> entrySet = map.entrySet();
        for (Map.Entry<String,String> entry:entrySet){
        // System.out.println (entry) ;
            System.out.println (entry.getKey() +"====>>"+entry.getValue());
        }