JAVA300集基础知识学习

算法网站:https://visualgo.net/

第5章 JAVA面向对象编程进阶

新建包的方法,按照域名倒着写可以保证包是唯一的

在这里插入图片描述

在包里可以新建类,目录树如下图
在这里插入图片描述

5.2

5.2.3 == 和equals 方法

package com.bjsxt.inherit;

import java.util.Objects;

public class User extends Object{

    int id;
    String name;
    String pwd;

    User(int id,String name,String pwd){
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public static void main(String[] args){

        User u1 = new User(1001,"张三","123456");
        User u2 = new User(1001,"李四","张三");

        System.out.println(u1);
        System.out.println(u2.toString());

        System.out.println(u1 == u2);

        System.out.println(u1.equals(u2));

    }
//这里是对Object中的equals方法进行了重写  重写后 两个对象的id相同 则认为两个对象相同
//不重写,使用默认的equals时,只有两个对象的地址相同时,才认为两个对象相同。
    public boolean equals(Object obj){
        if(obj==null){
            return false;  //return两个作用,返回值,结束方法运行
        }else {
            if(obj instanceof User){
                User u1 = (User)obj;
                if(u1.id == this.id){
                    return true;
                }
            }
        }
        return false; 
    }
}

在重写equals时,也可采用快捷键ALT+insert的方式进行 在自动生成的代码里 重写了equals 也重写了hashcode

在这里插入图片描述

在String类中,可以看到equals也被重写了

在这里插入图片描述

5.2.4 super关键字(看书)

5.4.2 封装的实现

先看一个小问题,`运行下列程序 会报错

package cn.sxt.gao7;

import cn.sxt.gao6.Person;

public class Student  {
    Person p1 = new Person();
    public static void main(String[] args){

        System.out.println(p1.toString());

    }


}

报错内容如图 ,分析:找不到p1变量 ,因为main函数中没有定义,没有对p1开辟地址 ,上文中虽然有p1但是属于 组合 的写法,并不是为p1分配地址
在这里插入图片描述
正确写法为

package cn.sxt.gao7;

import cn.sxt.gao6.Person;

public class Student  {

    public static void main(String[] args){
        Person p1 = new Person(); //此为更改内容
        System.out.println(p1.toString());

    }


}

5.9 接口 interface

5.9.1 Java8以后 新增特性

接口中允许默认方法

Java8 及以上旧版本,允许给接口添加一个非抽象的方法实现,只需要使用default关键字(这里的default和封装里的default是两码事)即可,这个特征又叫做默认方法(也称为扩展方法)
默认方法和抽象方法的区别时抽象方法必须要被实现,默认方法不是。作为代替方式,接口可以提供默认方法的实现,所有这个接口的实现类都会通过继承得到这个方法。
基本上不会用,某些开源软件里可能需要

package com.bjsxt.testInterface2;

public class Test {
    public static void main(String[] args){
        A a  = new Test_A();
        a.moren();

    }
}

interface A {
    default void moren(){  //注意默认方法和抽象方法是不同的           这里的default 和封装 里的default是不同的

        System.out.println("我是接口A中的默认方法!");

    }


}
class Test_A implements A{

	 @Override
	    public void moren() {
	        System.out.println("我BU是接口A中的默认方法!");
	    }
	}

}
接口中允许静态方法

Java8以后,我们也可以在接口中直接定义静态方法的实现。这个静态方法直接从属于接口(接口也是类,一种特殊的类),可以通过接口名调用。
如果子类中定义了相同名字的静态方法,那就是完全不同的方法了,直接从属于子类。可以通过子类名直接调用。
在这里插入图片描述

package com.bjsxt.testInterface2;

public class Test {
    public static void main(String[] args){
    //    B b  = new Test_B ();  //这样写是错误的
     //   b.staticMethod();  
          Test_B b  = new Test_B ();
          b.staticMethod();

         B.staticMethod();



    }
}
interface B{
    public static void staticMethod(){
        System.out.println("B.staticMethod");
    }
}

class Test_B implements B{

    public static void staticMethod(){
        System.out.println("Test_B.staticMethod");
    }

}
静态方法和默认方法

静态方法不能调用默认方法
默认方法可以调用静态方法

5.10 内部类

如何创建内部类对象
如何在内部类里调用外部类的属性

package com.bjsxt.testinertclass;
public class Outer1 {
    private int age =10;
    private void show(){
        System.out.println("你真好看");
    }
//内部类
    public class Inner1{
        private String name ="time";
        private int age =20;
        public void showInner(){
            System.out.println("Inner.showInner");
            System.out.println(age); //这里调用的是内部类的age变量
            System.out.println(Outer1.this.age); //这里调用的是外部类的age 当外部类属性
            //和内部类属性同名时,可以通过Outer1.this.age的方式调用
          //  System.out.println(Outer1.age); //这么写是错的
            show();//内部类可以直接使用外部类的成员
        }
    }
    public static void main(String[] args){
        Outer1.Inner1 inn01 = new Outer1().new Inner1(); //创建内部类的方式1
        inn01.showInner();
        Outer1 out02 = new Outer1();
        Inner1 inn02 = out02.new Inner1(); //创建内部类的方式2
        inn02.showInner();
    }
}

匿名内部类的使用

package com.bjsxt.testinertclass;
public class TestAnonymousInnerClass {
    public void test(A a) {
        a.run();
    }
    public static void main(String[] args) {
        TestAnonymousInnerClass tai = new TestAnonymousInnerClass();
       // AA aa = new AA();
        //tai.test(aa);
        //他就是匿名内部类 
        tai.test(new A(){
            @Override
            public void run() {
                System.out.println("窝嫩娘");
            }
        });
    }
}
interface A{
    void run();
}

//有名字的类 可以反复使用
class AA implements A {

    @Override
    public void run() {
        System.out.println("窝嫩爹");
    }
}

5.11.1 字符串比较

== 号 比较对象是否相同
在这里插入图片描述

equals 来比较两个字符串对象内容是否相同

7.1一维数组

所有的查找 需要按照新的规则 重新处理一遍
在进行索引时 包头不包尾 比如 索引2-6位置的元素 在下标上显示的就是a[2] a[3] a[4] a[5]

        Arrays.fill(a,2,6,100); //数组填充 或者其他方法查找 包头不包尾 java 字符串进行索引时 一般都是包头不包尾
        //即  2 3 4 5  包含2 不包含6

7.2 二维数组

二维数组可以看作是以数组为元素的数组,从内存分析过程就可以看出来
二维数组工作中不常用,后面会有容器相关方式等来代替
在这里插入图片描述

7.3 数组打印:Arrays.toString(数组名)

如下代码,为什么Arrays.toString(数组名) 不进行实例化后可以直接使用
可以按住alt键 在Arrays字母上左键单击,跳转到相应源码,可以发现toString()方法是静态方法
静态方法是可以直接用类调用的 其实就是类方法

package com.bjsxt.array;

import java.util.Arrays;

/**
 * 二维数组的练习
 * 使用Object[][]存储整个表格的数据
 */
public class Test09 {
    public static void main(String[] args){
        //每一个一维数组 代表一行数据
        Object[] emp0 = {1001,"高琪",18,"讲师","2006-2-14"};
        Object[] emp1 = {1002,"高小七",19,"助教","2007-10-10"};
        Object[] emp2 = {1003,"高小琴",20,"班主任","2008-5-5"};

       Object [][] emps = new Object[3][];
       emps[0] = emp0;
       emps[1] = emp1;
       emps[2] = emp2;

       //打印
        System.out.println(Arrays.toString(emps[0])); //Arrays.toString 未进行实例化
        System.out.println(Arrays.toString(emps[1]));
        System.out.println(Arrays.toString(emps[2]));
        Test10.print();
    }


}

8 使用Javabean和数组存储表格的信息,这个方式非常重要,后面天天用(120节)

package com.bjsxt.array;

public class Test11 {

    public static void main(String[] args) {
       //在某行前 按 crtl+d可以将改行复制到下一行
        Emp emp0 = new Emp(1001,"高效益",18,"程序员","2019-9-9");
        Emp emp1 = new Emp(1002,"高度J",18,"程序员","2019-9-10");
        Emp emp2 = new Emp(1003,"高反对",18,"程序员","2019-9-11");

       // Emp[] emps = {emp0,emp1,emp2}; //静态初始化

        Emp[] emps = new Emp[3]; //动态初始化
        emps[0] = emp0;
        emps[1] = emp1;
        emps[2] = emp2;

        for (int i = 0;i< emps.length;i++)
        {
            System.out.println(emps[i].toString());

        }
    }

}
class Emp {
    private int id;  //使用javabean封装
    private String name;
    private int age;
    private String job;
    private String hiredate;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getJob() {
        return job;
    }

    public String getHiredate() {
        return hiredate;
    }
    public Emp(){}  //一般情况下建议有 无参构造器
    public Emp(int id, String name, int age, String job, String hiredate) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.job = job;
        this.hiredate = hiredate;
    }

    @Override
    public String toString() {
        //制表符 \t
        //最好是用getName这种形式,方便改变,属性不方便改,但是getName等函数可以很方便的改
        return getId()+"\t"+getName()+"\t"+getAge()+"\t"+getJob()+"\t"+getHiredate();
    }
}

输出结果为
“C:\Program Files\Java\jdk-13.0.2\bin\java.exe” “-javaagent:E:\javasoft\idea2020\IntelliJ IDEA 2020.2.4\lib\idea_rt.jar=52780:E:\javasoft\idea2020\IntelliJ IDEA 2020.2.4\bin” -Dfile.encoding=UTF-8 -classpath C:\Users\gou\IdeaProjects\wang01\out\production\wang01 com.bjsxt.array.Test11
1001 高效益 18 程序员 2019-9-9
1002 高度J 18 程序员 2019-9-10
1003 高反对 18 程序员 2019-9-11

9 泛型

9.2.1 定义泛型

泛型字符可以是任何标识符,一般采用几个标记:E,T,K,V,N,?

泛型标记对应单词说明
EElement在容器中使用,表示容器中的元素
TType表示普通的JAVA类
KKey表示键,例如:Map中的键Key
VValue表示值
NNumber表示数值类型
表示不确定的JAVA类

9.2.1 泛型类

泛型类就是把泛型定义在类上,用户使用该类的时候,才把类型明确下来。泛型类的具体使用方法是在类的名称后添加一个或多个类型参数声明,如: `,<T,K,V>

语法结构
`public class 类名<泛型表示符号>{

}`

例子

/*
创建一个泛型类 Generic
*/
public class Generic <T>{   //这里用T表示普通的泛型类
    private T flag;
    public void setFlag(T flag){ 
        this.flag = flag;
    }
    public T getFlag(){

        return this.flag;
    }
}
/*
测试这个泛型类
 */
public class Test {
    public static void main(String[] args) {
        Generic<String> generic = new Generic<>(); //这里对泛型类进行使用 
        //传递的是String 也就是说在 创建泛型类的时候,不用关心所传递的是什么参数 到调用的时候在考虑就可以。方便编程
        generic.setFlag("admin");
        //generic.setFlag(100);  出现编译报错,因为已经确定要传的类是String类 不能再传int 了。
        String flag = generic.getFlag();
        System.out.println(flag);
        Generic<Integer> generic1 = new Generic<>(); //这里传递的是包装类
        generic1.setFlag(100);
        Integer flag1 = generic1.getFlag();
        System.out.println(flag1);
    }
}

9.2.2 泛型接口

泛型接口 泛型接口和泛型类的声明一致。泛型接口的具体类型需要在实现类中进行声明
语法结构 public interface 接口名<泛型表示符号>{ }

例子

/**
 * 定义一个泛型接口 
 */
public interface Igeneric<T> {
    T getName(T name);   //
    
}
/**
 * 实现定义的泛型接口
 * 可以发现 原来的T变成了 String
 * 重写getName方法时,返回的类型也是String
 */
public class IgenericImpl implements Igeneric<String>{

    @Override   //按下alt+insert键,插入getName键,可以发现方法的返回值就是String
    public String getName(String name) {
        return name;
    }
}
/**
 * 创建一个测试类,测试泛型接口
 */
public class Test22 {
    public static void main(String[] args) {
        IgenericImpl t1 = new IgenericImpl();
        System.out.println(t1.getName("wonendie"));
        
        Igeneric igeneric1 = new Igeneric() {
            @Override    //直接引用接口,没有给定泛型类型,默认返回的就是Object
            public Object getName(Object name) {
                return null;
            }
        };
        Igeneric<String> igeneric2 = new Igeneric<String>() {
            @Override    //引用接口时定义泛型类型为String,重写方法时直接返回String
            public String getName(String name) {
                return null;
            }
        };
    }
}

9.2.3 泛型方法

泛型类中所定义的泛型,在方法中也可以使用。 但是,我们经常需要仅仅在某一个方法上使用泛型,这时候可以使用泛型方法。
泛型方法是指将方法的参数类型定义成泛型,以便在调用时接受不同类型的参数。 类型参数可以有多个,用逗号隔开,如<K,V>。定义时,类型参数一般放到返回值前面。
调用泛型方法时,不需要像泛型类那样告诉编译器是什么类型,编译器可以自动推断出类型来。

9.2.3.4 非静态方法

语法结构
public <泛型表示符号> void getName(泛型表示符号 name){ }
public <泛型表示符号> 泛型表示符号 getName(泛型表示符号 name) {
}

示例

/**
 * 定义一个泛型方法
 */
public class MethodGeneric {

    /**
     * 定义了一个泛型方法,无返回值
     * @param name
     * @param <T>
     */

    public <T> void setName(T name){
        System.out.println(name);
    }

    /**
     * 定义了一个泛型方法,有返回值
     * @param name
     * @param <T>
     * @return
     */

    public <T> T getName(T name){
        return name;
    }
}
/**
*调用泛型方法
*/
public class Test33 {

    public static void main(String[] args) {
        MethodGeneric methodGeneric = new MethodGeneric();
        /**
         * 可以看到 传递什么类型都可以
         */
        methodGeneric.setName("oldru");
        methodGeneric.setName(1233333);
        MethodGeneric methodGeneric11 = new MethodGeneric();
        System.out.println(methodGeneric11.getName(12333));
        System.out.println(methodGeneric11.getName("dsfdfd"));

    }
    
}

9.2.3.5静态方法

静态方法中使用泛型时有一种情况需要注意一下,那就是静态方法无法访问类上定义的泛型;如果静态方法操作的引用数据类型不确定的时候,必须要将泛型定义在方法上

public class Generic <T>{
    private T flag;
    public void setFlag(T flag){
        this.flag = flag;
    }
    /**
     * 定义静态方法 报错 报错原因:在静态方法中,泛型是不允许使用类中所定义的泛型的
     * 这是泛型非静态方法和泛型静态方法的一个重要区别
     * @param name
     * @return
     */
    public static T demo(T name){
        return null; //报错  在静态方法当中,泛型是不允许使用类中所定义的泛型的 
        
    }
    public T getFlag(){
        return this.flag;
    }
}

语法结构

public static <泛型表示符号> void getName(泛型表示符号 name){
}
public statci <泛型表示符号> 泛型表示符号 getName(泛型表示符号 name){
}

示例

/**
 * 定义一个静态泛型方法
 */
public class MethodGeneric {

    public static <T> void setFlag(T flag){
        System.out.println(flag);
    }

    public static <T> T getFlag(T flag){
        return flag;
    }
}

调用静态方法 静态方法调用不需要实例化,直接通过类名就可以

public class Test44 {
    public static void main(String[] args) {
        //静态方法的调用不需要实例化,直接通过类名就可以
        MethodGeneric.setFlag("oldlu");
        int a = MethodGeneric.getFlag(123);
        System.out.println(a);
    }
}

9.2.4 泛型方法与可变参数

在泛型方法中,泛型也可以定义可变参数类型

语法结构

public <泛型表示符号> void showMsg(泛型表示符号...agrs){

}

示例

/**
 * 定义一个可变参数的泛型方法
 */
public class MethodGeneric {

    public <T> void method(T...args){
        //可变参数是一个数组,直接遍历
        //增强for循环遍历数组
        for(T t:args){
            System.out.println(t);
        }
    }
}

调用泛型方法

public class Test5 {
    public static void main(String[] args) {
        MethodGeneric methodGeneric = new MethodGeneric();
        String[] arr = new String[]{"a","b","c"};
        methodGeneric.method(arr);

        Integer[] arr2 = new Integer[]{1,2,3};
        methodGeneric.method(arr2);
    }
}

9.2.5 通配符和上下限定

9.2.5.1 无界通配符 (171集 6:10)不太懂 回头看

“?” 表示类型通配符,用于代替具体的类型。它只能在"<>"中使用。可以解决当具体类型不确定的问题

语法结构

public void showFlag(Generic<?> generic){

}

示例

/*
*用通配符创建方法
 */
public class ShowMsg {
    public void showFlag(Generic<?> generic){
        System.out.println(generic.getFlag());
    }
}

调用

/**
 * 调用方法
 */
public class Test6 {

    public static void main(String[] args) {

        ShowMsg showMsg = new ShowMsg();

        Generic<Integer> generic = new Generic<>();
        generic.setFlag1(20);

        showMsg.showFlag(generic);


        Generic<Number> generic1 = new Generic<Number>();
        showMsg.showFlag(generic1);

        Generic<Integer> generic2 = new Generic<Integer>();
        showMsg.showFlag(generic2);

    }
}

9.2.5.2 通配符的上限限定

上限限定表示通配符的类型是T类以及T类的子类或者T接口以及T接口的子接口。
该方式同样适用于泛型的上限限定

语法结构
这个Generic是什么?

public void showFlag(Generic<? extends Number generic){

}   
/**
*这里的?继承于Number 因此?只能是Number或者Number的子类

示例:
1.通配符加了上限限定,调用该方法时,传进去的参数只能是其子类
在这里插入图片描述
在调用时会发生报错,因为String不属于Number或者Number的子类

9.2.5.3通配符的下限限定

  • 下限限定表示通配符的类型是T类以及T类的父类或者T接口以及T接口的父接口
    注意:该方法不适用于泛型类
  • 语法结构
public void showFlag(Generic<? super Integer> generic){


}

示例
改成下限限定在这里插入图片描述
发现报错
因为Integer不是Number的父类在这里插入图片描述

9.2.6 泛型总结

  • 自我总结1:泛型说白了就是 类 接口 方法 传参的时候,不需要确定参数的类型,实际使用的时候再传就行。和C语言对比,C语言中函数在传参时必须要定义参数的数据类型,但JAVA中的泛型就不需要,方便了程序员。

  • 自我总结2:泛型和Object比较;泛型不需要显示类型转换,即在使用的时候不需要用instanceof判定,但Object中 转化成 具体类型时,需要用instanceof关键字判定,否则可能会编译出错。

  • 自我总结3:和C语言中的预编译进行比较,泛型也是在运行时会被替换成其他类(Object类)。有点类似,但又所不同?

  • 老师总结:
    泛型主要用于编译阶段,编译后生成的字节码class文件不包含泛型中的类型信息。 **类型参数在编译后会被替换成Object,运行时虚拟机并不知道泛型。因此,使用泛型时,如下几种情况是错误的:
    1.基本类型不能用于泛型。

    基本类型不能用于泛型。
    Test<int> t; //这样写法是错误的,我们可以使用对应的包装类:Test<Inerger> t;
    不能通过类型参数创建对象
    T elm = new T(); //运行时类型参数T会被替换成Object,无法创建T类型的对象,容易引起误解,所以在Java中不支持这种写法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java基础需要学习的知识包括但不限于以下内容: 1. Java的基本语法,如变量、数据类型、运算符、条件语句、循环语句等; 2. 面向对象编程的概念,如类、对象、继承、多态等; 3. Java中的异常处理机制,如try-catch语句、throw语句等; 4. Java中的合框架,如List、Set、Map等; 5. IO流和文件操作; 6. 网络编程和Socket编程; 7. 多线程编程。 除了以上基础知识外,还可以学习Java的高级特性,如反射、注解、泛型等,以及常用的框架,如Spring、Hibernate等。同时,也可以学习Java在各种应用场景中的应用,如Web开发、移动应用开发、大数据处理等。 ### 回答2: 学习Java基础知识是成为一名优秀的Java开发人员的必要步骤。下面是一些需要学习的主要知识点: 1. Java语言基础:包括Java的历史、特性、语法、标识符、变量、数据类型、运算符等。这些是理解和编写Java程序的基础。 2. 面向对象编程(OOP):理解面向对象编程的概念和原则,例如封装、继承和多态。学习如何创建和使用类、对象和方法。 3. 控制流程:了解条件语句(if-else、switch)、循环语句(for、while、do-while)和跳转语句(break、continue)的使用方法。 4. 数组和合:学习如何创建和使用数组,并了解常见的数据结构例如ArrayList、LinkedList和HashMap等。这些是处理大量数据的重要工具。 5. 异常处理:学习如何检测、抛出和捕获异常。理解处理异常的重要性,以及如何有效地处理错误和异常。 6. 输入输出(I/O)操作:了解如何读取和写入文件、处理用户输入和输出。学习如何使用Java的I/O类进行文件和流的操作。 7. 多线程编程:了解多线程的概念、实现和管理。学习如何创建和启动线程,并掌握同步和互斥的概念。 8. JDBC和数据库操作:学习如何连接和操作关系型数据库,如MySQL、Oracle等。了解SQL语句的基本语法,以及如何使用Java中的JDBC API进行数据库操作。 9. 常用类库:学习使用Java的常用类库,如日期和时间类、字符串处理类、正则表达式类等。了解常用类库的功能和使用方法,提高编程效率。 除了上述知识点,还需要不断练习编程,进行项目实战,提升自己的实际应用能力。同时还可以通过阅读相关的书籍和参与开发社区的讨论,来不断拓展和深化自己的Java基础知识。 ### 回答3: Java是一种广泛应用的编程语言,作为学习Java基础的人,需要掌握以下几方面的知识。 首先,Java语言的基本语法学习的重点,包括变量的声明与使用、数据类型、运算符、控制语句(if-else、for、while等)、数组、字符串等。掌握这些基本语法是理解Java程序的基础。 其次,面向对象思想是Java的核心。需要学习类与对象的概念,如何定义和使用类、继承、封装、多态等。掌握面向对象思想可以让程序更加模块化、可维护和扩展。 此外,Java的异常处理机制也是需要掌握的重要知识。学习如何使用try-catch语句处理异常,如何创建自定义异常类以及如何处理异常的传递和捕获。合理的异常处理可以提高程序的健壮性和可靠性。 最后,Java的标准库也是需要学习的内容,例如输入输出流、合类、多线程等。了解这些标准库的用法可以提高编程效率,并且可以更好地完成各种编程任务。 综上所述,学习Java基础需要掌握的知识包括基本语法、面向对象思想、异常处理机制以及Java标准库的使用。通过学习这些知识,可以打下扎实的编程基础,并为进一步深入学习Java高级特性和应用开发打下坚实的基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值