重生之我在地球Online当程序员9

拓展

一、常量

之前学过“变量” , 今天了解常量!

常量:内容不能修改的量!

public static void main(String[] args) {
    int r = 4;
    //常量的命名规则:常量名 应该全大写
    final double PI = 3.14;
    System.out.println(PI * Math.pow(r,2));
}

常量使用final 来进行进行修饰!

final 只能用来修饰常量么?答案不是,final除了可以修饰常量,还可以修饰方法,以及修饰类!

//final修饰的类,是最终类,太监类
//不能被继承的类
public final class Human {
    //常量:染色体的数量
    public static final int CHROMOSOME_NUMBER = 46;
    //final 修饰方法,表示:该方法不能被子类重写
    //因为它是最终方式
    public final void study(){
        System.out.println("你好!");
    }
}

eg:String 其它的包装类 Integer Long Double Float Short Byte Character Boolean

二、ArrayList

ArrayList 是个List集合,作用:存储大量的相同/相似的数据!

底层:数组

特点:

1.有序,添加的顺序&输出的顺序是一样的

2.可以存放重复数据

public class MainEnter {
    public static void main(String[] args) {
        List<String> datas = new ArrayList<>();
        datas.add("张三");
        datas.add("李四");
        datas.add("王五");
        datas.add("张三");
        for (String data : datas) {
            System.out.println(data);
        }
    }
}
三、HashSet
public class MainEnter {
    public static void main(String[] args) {
        //需求:不希望有重复数据
        Set<String> datas = new HashSet<>();
        datas.add("张三");
        datas.add("李四");
        datas.add("王五");
        datas.add("张三");
        for (String data : datas) {
            System.out.println(data);
        }
    }
}

特点:

1.无序

2.去重

四、补充

1.双层循环中,一个变量定义在外层,内层,夹层,有什么不同?

2.java中有没有goto关键字?有没有什么语法可以变通出goto流程?

-循环标签

goto 在c语言中,用来跳转指针使用!Java中确实存在这个关键字,但是没有用!

3.递归,可用斐波那契数列和阶乘举例.既能递归又能循环,如何选择?什么场合只能递归?

遍历:使用循环,将集合或数组中的每个元素 都取出来!

递归:方法自己不断的调用自己!

需求:

public class MainEnter {
    public static void main(String[] args) {
        login();
    }
    public static void login(){
        System.out.println("输入你的登录名:");
        System.out.println("输入你的密码:");
        login();
    }
}

image-20240518144531490

当递归使用不当的情况,可能出现:栈溢出的错误

image-20240518144929639


解决方案:

public class MainEnter {
    public static String account = "admin";
    public static String pwd = "123456";
    public static void main(String[] args) {
        if(login()){
            System.out.println("登录成功,系统即将跳转首页!");
        }
    }
    public static boolean login(){
        boolean flag = false;
        System.out.println("输入你的登录名:");
        String loginName = new Scanner(System.in).next();
        System.out.println("输入你的密码:");
        String password = new Scanner(System.in).next();
        if(loginName.equals(account) && password.equals(pwd)){
            flag = true;
        }else{
            flag = login();
        }
        return flag;
    }
}
五、JVM在运行期间的内存分配

JVM :Java虚拟机!

作用:为Java程序提供一个运行的环境!

特点:不同的操作系统,具有不同的JVM环境!才能做到“跨平台”

image-20240520094229502

:是一种上开下闭的数据结构,空间中主要存储:方法,已经方法中定义的变量

:放置new出来的对象,字符串常量池

程序计数器:记录代码的执行顺序

本地方法栈:存储跟底层操作系统有关的方法,通常这种方法都是C语言编写的

元空间:在JDK1.7时,也是存放在JVM内部的。但是在JDK1.8时,已经存放在物理内存中,

public class MainEnter {
    public static void main(String[] args) {
        int a = 10;
        int b = 12;
        String str = new String("张三");
        Student stu = new Student(1,"李四");
    }
}

image-20240520100118368

Java有2种数据类型:基本数据类型,引用数据类型

基本数据类型:变量 & 值 位于同一个地方!

引用数据类型:变量中存储的是 对象的内存地址,而不是具体的内容!

六、Java的值传递

方法中传入对象,并且针对对象的内容进行修改,请问这个是值传递还是引用传递?

image-20240520101034795

public static void main(String[] args) {
    Student stu = new Student(1,"张三");
    modifyStudent(stu);
    System.out.println(stu);
}
public static void modifyStudent(Student student){
    student.setName("李四");
}

image-20240520103626492

基本数据类型,在传递时,复制的是变量的值!

引用数据类型,在传递时,复制的也是变量的值!只不过这个值,是地址值而已!

七.关于static,静态成员与实例成员的区别.

-静态成员属于类,多个对象间共享.

-非静态成员属于对象

静态的成员,因为它是类的东西,所以调用方式:类名.属性    类名.方法()非静态的成员,因为它是对象的东西,所以调用的方式:对象.get属性()    对象.方法()

静态的方法,不能直接调用 非静态的属性/方法!

非静态的方法,可以直接调用 静态的属性/方法!


什么叫多态.

多态:相同的行为,不同的实现!

具体的体现方式:

-父类的引用指向子类的对象

-接口的引用指向实现类的对象

-多态时,方法名列表看父类,执行过程看子类.

-常规类->抽象类->接口 : 三者从大范畴上都属于类,三者的演变是一个逐步变得残缺的过程.


重载与重写.

-同一个类里,两个方法,同名不同参,叫作重载.

-注意同名又同参,但返回不同,不能构成重载.

-两个类里,子类重写父类方法,实现类重写接口方法.

八.谈谈堆,栈,常量池,以及无限递归为什么发生栈溢出?常量池的去重特性是什么?如何证明?

-基础型数据存栈

-对象型数据,引用部分存栈,对象内容部分存堆.

-字符串可以存常量池,可以存堆.

-堆空间受垃圾回收机制管理,不易溢出.

public class MainEnter {
    public static void main(String[] args) {
       String a = "张三";
       String b = "李四";
       String c= "张三";
       //常量池:张三,李四
    }
}
//JVM在加载时,就会针对 字符串常量进行去重操作!
//校验方式,使用JAVA/bin目录下的javap工具,具体的命令:javap -v 类名.class
九.List与Set的区别,Arraylist与LinkedList的区别,HashSet与TreeSet的区别.

-List有序, 不去重

-Set无序, 去重

(HashSet内在顺序不可自定义,TreeSet内在顺序可以自定义,通过传入比较器.)

-少数非主流list或set不符合以上规则.

-ArrayList底层是数组,读取快,增删慢.LinkedList底层是双向链表,读取慢,增删快.

image-20240520114216147

十.==/equals()/hashcode()区别?String的equals()与hashcode()为什么针对内容?

-默认对象中,三者均针对地址.

-==不可重写,后二者可重写,重写后可以针对地址,也可以针对内容.

-String中的equals()/hashcode()都是重写过的,所以针对内容.

-对于一个自定义类,我们一旦重写了equals(),就要同步重写hashcode(),这个规范是用来满足set类集合判重的.

public class Suspect {
    private int id;
    private String name;
    private String idcard;
    private String dna;
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Suspect suspect = (Suspect) o;
        return Objects.equals(dna, suspect.dna);
    }
    @Override
    public int hashCode() {
        return Objects.hash(dna);
    }
    //getter()  & setter()
    //toString()
}
public class MainEnter {
    public static void main(String[] args) {
        //分析DNA的结果是
        Suspect suspect = new Suspect("张三","10086","111");
        //现在有3个嫌疑人
        Suspect a = new Suspect("李四","10001","222");
        Suspect b = new Suspect("王五","345345","111");
        Suspect c = new Suspect("赵六","12315","333");
        //找到罪犯
        System.out.println(suspect.equals(a));
        System.out.println(suspect.equals(b));
        System.out.println(suspect.equals(c));
    }
}
​

为什么重写了equals() ,还要重写hashcode() ?

System.out.println("Aa".hashCode());  //hashcode = 2112
System.out.println("BB".hashCode());  //hashcode = 2112
在Java中,可能出现:
    不同的对象,可能具有相同的Hash值!
    相同的对象,他们的Hash值一定相同!

所以,HashSet 去重的原理是:先比较内存地址的值,然后再比较内容的值!

image-20240520142533532

所以:

public class MainEnter {
    public static void main(String[] args) {
        Suspect suspect = new Suspect("张三","123","111");
        Suspect a = new Suspect("李四","234","222");
        Suspect b = new Suspect("张三","123","111");
        Suspect c = new Suspect("赵六,"456","333");
        //这里要想实现:根据dna去重,需要在Suspect 根据dna重写equals() & hashcode()
        Set<Suspect> sus = new HashSet<>();
        sus.add(suspect);
        sus.add(a);
        sus.add(b);
        sus.add(c);
        System.out.println(sus.size());
        for (Suspect sus1 : sus) {
            System.out.println(sus1);
        }
    }
}

UserInfo 属性:id(int),name(String) ,age(int) ,idcard(String) , blood(String)

要求:

1、所有的属性私有化,提供getter & setter ,toString()

2、在MainEnter的main() 中,创建2个UserInfo ,只要idcard & blood一致,就认为这2个对象,是同一个对象!

十一、HashSet & Treeset的区别

HashSet & Treeset 都是Set集合的实现类,都可以实现内容的去重!

HashSet 去重的原理:先比较hashcode的值,想通的hashcode,然后再调用equals() 方法完成去重!

HashSet 是无序的,内部可能有顺序!

TreeSet 打印顺序&存放的顺序仍旧不同,但是内部的元素是进行排序的!

TreeSet 根据比较器来完成去重!当比较器的值=0,表示两个对象是同一个对象!

public class MainEnter {
    public static void main(String[] args) {
        Set<Integer> datas = new TreeSet<>();
        datas.add(11);
        datas.add(9);
        datas.add(5);
        datas.add(22);
        for (Integer data : datas) {
            System.out.println(data);
        }
    }
}

如何实现排序的呢?依靠:Comparator 比较器


两种比较器Comparator & Comparable

public class Student implements Comparable<Student>{
     @Override
    public int compareTo(Student o) {
        return o.getAge() - this.getAge();
    }
}

但是:程序员为了减少代码的 耦合度,于是:喜欢使用Comparator

十二、匿名内部类

内部类:定义在类内部的类!不是问你:累不累?

匿名内部类:一个没有名字的内部类!

public class MainEnter {
    public static void main(String[] args) {
        //使用匿名内部类,定义比较器
        Comparator<Student> comparator = new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o2.getAge() - o1.getAge();
            }
        };
        List<Student> stus = new ArrayList<>();
        stus.add(new Student("张三",22));
        stus.add(new Student("张三",18));
        stus.add(new Student("张三",26));
        stus.add(new Student("张三",15));
        Collections.sort(stus,comparator);
        //需求:按照年龄 升序排列
        for (Student student : stus) {
            System.out.println(student);
        }
    }
}

public class MainEnter {
    public static void main(String[] args) {
        //卖手机
        Goods g1 = new Goods("iphone20",20000,200);
        Goods g2 = new Goods("huaweimeta60",12000,120);
        Goods g3 = new Goods("xiaomi14plus",22000,200);
        List<Goods> goods = new ArrayList<>();
        //将3台设备,添加到goods集合中去
        Collections.addAll(goods,g1,g2,g3);
        //先按照销量排序,再按照价格排序
        Collections.sort(goods, new Comparator<Goods>() {
            @Override
            public int compare(Goods o1, Goods o2) {
                int i = o2.getSellNumber() - o1.getSellNumber();
                if(i == 0){//销量一样,再按照价格升序
                    return o1.getPrice() - o2.getPrice();
                }else{
                    return i;
                }
            }
        });
        //打印输出:排序的结果
        for (Goods good : goods) {
            System.out.println(good);
        }
    }
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值