Java基础语法笔记

Data:2022/10/22
Author:文东柳

构造器

构造器通常也叫构造方法、构造函数,构造器在每个项目中几乎无处不在。当你new一个对象时,就会调用构造器。构造器格式如下:

[修饰符,比如public] 类名 (参数列表,可以没有参数){ //这里不能有return}

在java中,构造器的的名字与类的名字是一致的。

数组

数组定义示例:

int[] a = new int[10];
int[] b = {1,2,3,4,5..,n};

可以通过new方法来声明一个新数组,亦可通过直接赋值的方式创建一个新的数组,数组成员的数量即为元素的个数。

遍历数组

常规的循环方式有While()、for(),对于for循环有一种特殊的形式,叫做FOR-EACH循环,其用法示例如下(假设date为某一个已初始化的数组):

/* 
使用格式
for(<类型><变量>:<数组>)
{
    ....;    
}
*/

for(int k : date);
    {
        system.out.println(k);
    }

对于这个循环,每循环一次都会将date的值取出,传入到k中保存,对于需要遍历数组而言,这个循环十分的适合。但是有一个弊端,你无法知道这个k值是date的第几个数值(可以考虑通过添加循环计数变量实现记录,但是这样的话跟普通的for循环相比就没有差别了)。每一轮循环,k它实质上是date的复制品,它无法实现类似k++的操作。

字符类型

逃逸字符


逃逸字符是一些没法直接打印出来的字符,它由反斜杠''开头,后面跟上另一个字符,共同组成一个逃逸字符。

字符串操作

两个字符串比较大小:

s1.compareTo(s2)
这个示例给出了s1和s2之间大小的比较方法,区分大小写,比较的方式是通过unicod编码进行比较,java使用的是unicode编码的方式。如果s1<s2,得出负的;反之为正,相等为0。在s1的位置,不一定得是字符串变量,可以是常量或者带有双引号的字符串。

获得String的长度:

length()
该函数可以得出长度,示例如下:

String name = "Hello";
str1 = "one";
str2 = "";
str3;

name.length();//7
str1.length();//3
str2.length();//0
str3.length();//Error!
/*
str3.length();输出错误的原因是该字符串变量未有指向的字符串所在内存地址。
*/ 

访问String里的字符

s.charAT(index)
返回所在index上的单个字符。对于字符串不能用for-each循环遍历。

字符串取子字符串操作

s.subString()
使用该方法可以实现。括号里给出单个数字,则输出从相应数字序号开始之后的字符串;如果给出范围,则从第一个数开始直到最后一个数的前一个数截至,取出相应位置的字符串。

寻找字符串

字符串

对于java的字符串string,其可理解为一个单个的字符数组,其指向下标为0的第一个字符的内存地址。而对于string的数组,其可理解为一个指针数组,其指向一个存放了多个指针的、下标为0的数组内存地址。

函数

函数定义

//以一个求和函数,来展示常见的函数定义方式:

public static void sum(int a, int b)
{
    int i;
    int sum = 0;//java会默认给变量初始化为0,此时手动对其初始化是一种冗余的行为。
    for(i=a;a<=b;i++)
    {
        sum-=i;
    }
    system.out.println(a+"到"+b+"的和是"+sum);
}

一、类与对象

对象初始化

对象初始化

//<类型(私有、公有> <类> <对象名> = new <类>;
//示例,在某一个类中创建私有化的成员对象hour、minute:
public class Clock
{
    private Display hour = new Display(24);
    private Display minute = new Display(60);
    
    public static void main(String[] args)
    {
        //TODO
    }
}

二、对象交互

对象交互

对象的交互

一个类的成员可以是其他类的对象,例如如下代码:

public class Display
{
    //这是一个类
}

public class Clock
{
    private Display hour=new Display(24);
    private Display minute=new Display(60);
    //另一个类的对象可以是这个类的成员
}

访问属性

封闭的访问属性


除非有特殊的理由,否则所有的类成员都应该是私有的。私有针对的是类,判断访问是否合法,应该看对私有成员的操作是否是在类的范围内,只要是在类的范围内,都合乎法则,即使是同一个类的不同对象,也能够互相访问对方的私有成员。

开放的访问属性


如果一个类成员没有用private or public来限定它,则这个类成员我们称之为friendly。对于这种类型的类成员,只要是与这个类在同一个包(包的含义请见下文)下的所有函数,均可以访问它。

对于一个类,其名字必须与类的文件名完全一致,且它必须为public类型。

一个.java文件称之为一个【编译单元】。一个.java文件里边可以有很多个类,但能有一个类可以和文件名一致,且只有这个函数可以是public类型,其他类不可以。


在这里,最上方的clock为项目名称,下方的src意味存放源代码,再下方的clock为“包”,display也是“包”。
import的用法:.<包>.<类>。如果需要引用其他包的类,需要通过import来进行引用。当然,也可以不通过import的方式来使用其他包的类,通过<包>.<类>也是可以直接声明和生成其他包的类的对象。
java也可以在“包”里边在生成“包”。

类变量

类变量

在类中以static来声明成员变量,称之为类变量。该变量属于类本身,而不像其他类的对象一样各自有属于自己的变量,类变量可以直接通过<类>.<类变量>来访问与控制,也可以通过<类>.<类变量>来访问与控制类变量,无论是哪种方式,他们实际上操作的是同一个变量,当其值有改变时,无论是类或者成员再调用或访问它的时候,它的值都是改变后的值。

类函数

与类变量一致,亦可在声明类的成员函数时,可以添加上static,使其变成类函数,其属于类,而不属于任何该类下的任何成员,它与对象无关系。static的函数只能访问static的函数,只能访问static的成员变量。static的函数与变量都可以通过类的名字去访问,也可以通过某个对象去访问,但是通过对象去访问的时候它没法得到那个对象的具体信息。

封装
对于java,有privatepublic两种常用的函数头,分别表示私有的和共有的。对于声明为private的类成员,仅能允许属于该类的对象访问这个成员,及时是同一个类的不同成员,也能互相访问另一个对象的private成员,但不属于该类的成员就无法访问了。private只能用于成员变量或者成员函数。私有针对的是类,而不是对象,这点小细节需要留意。

对于public,其意义为公有的意思,它可以在任意位置访问和使用。

对于未声明为publicprivate的类成员,其为friendly类型,即为友元类型。作用是与这个类位于同一个包下的成员,均可以访问它。

对象=属性+服务
数据:属性或者状态
操作:函数
把属性和对数据的操作放在一起->封装

对于public的类,其类名必须与其文件名一致。
当一个编译单元(可以理解为一个源文件的意思)有多个类时,仅只能有一个类可以是public

三、对象容器

顺序容器

泛型容器类


声明模板

ArrayList<例如String的对象> 名字 = new ArrayList<例如String的对象>();

我们把它称之为用于存放stringArrayList,我们把这种类型叫做泛型类。
容器类有两个类型:容器(ArrayList)的类型和元素(string)的类型。

ArrayList的操作

//ArrayList的一些方法函数
.add(添加的位置,要添加的值)//用于向容器的尾部添加值,同时也可以指定在某个位置的前面,也可以不指定,则默认在容器尾部。
.size()//返回容器中有多少东西
.get(integerNubmer)用于返回ArrayList容器中下标为"integerNumber"的数据
.remove(指定位置)//删除成功则返回删除的内容,越界了的话抛出异常
.toArray(数组变量a)//自动将容器中的值填到a中。

对象数组

对象数组

String[] a=new String[integer];//新建了一个对象数组,数组的大小为integer。

其本质为一个指针数组,其中每一个元素为一个指向了String类型数据的内存地址。

对象数组的for-each循环

//此处省略掉与对应编译单元文件名字一致的函数函数代码
class Value
{
    private int i;
    public void set(int i)
    {
        this.i=i;
        /**这里的this用于指代该类的对象
        *该类实例化的对象在调用该方法时,其对象本身用this来指代。这个语句的意思即为“这个对象的i等于成员函数所接收的i”。
        */
    }
    public int get()
    {
        return i;
    }
}
//此处省略一些代码,以下为编译单元的主函数
public static void main(String[] args)
{
    Value[] a = new Value[10];
    for(int i=0;i<a.length;++i)
    {
        a[i] = new Value();
        a[i].set(i);
    }
    for(Value v : a)
    {
        System.out.println(v.get());
    }
}

对于ArrayList容器亦是可以使用该循环的。

集合容器(set)

集合容器

实例化该泛型容器类的方式请见下方

HashSet<String> s = new HashSet(String);

s.add("first");
s.add("second");
s.add("first");
for(String k : s)
{
    System.out.println(k)
}

/**output:
*first
*second
*/

这类容器存放的数据不重复,且元素之前并没有排列次数的关系。

这次穿插一个有关String的知识点,对于任意一个类,只要实现了一个public String toString(){};,有了这个函数以后,就可以直接用System.out.println()这个语句来输出相应的对象,它会主动的取调用我们的toString()函数,用这个函数产生的String来产生输出。

散列表(Hash)

Hash表

这个Hash表对应着编程中的“键值对”概念,这个表既是java的键值对实现。实现方式如下:

public class Coin
{
    private HashMap<Integer,String> coinname =new HashMap<Integer,String>();
    
    public Coin()
    {
        //这是一个格式模板conname.put(key,value);
        coinname.put(5,"penny");
        coinname.put(10,"dime");
        coinname.put(25,"quarter");
        coinname.put(50,"half-dolar");
        System.out.println(coinname.KeySet().size());
        //这一个语句的作用是输出这个键值对一共存在多少个键。
    }
    //这是一个Coin的构造器
    
    public String getName(int amount)
    {
        if (coinname.containsKey(amount))
        {
            return coinname.get(amount);
        }
        //此段的作用是判断 键值对 中是否有键与这个值对应。
        else
        {
            return "NOT FOUND";
        }
    }
    
    public static void main(String[] args)
    {
        Scanner in =new Scanner(System.in);
        int amount = in.nextInt();
        Coin coin =new Coin();
        String name = coin.getName(amount);
        System.out.println(name);
    }
}

在这里强调一个知识点,对于java这个面向对象的编程语言来说,Hash表是一种容器,这个容器里边所有的类型必须得是对象,而不能是基本类型。String可以、Integer可以(这个是int的包裹类型)
一个包裹类型的变量可以接收它所对应类型的基本变量。
Hash表的一些方法:

.KeySet();//这个可以返回所有键的集合
.get(Key);//返回特定键所对应的值
.containsKay(Key);//判断在这个键值对中是否有叫做"Key"的键。是返回true,否返回false。

四、继承与多态

继承

媒体资料库的设计


这是一条分割线----------------------------------

插入知识点函数的重载
函数名一致,但是形参不一致,就成为函数的重载。

继承

假设现在有三个类,分别是Item、CD、DVD。
Item里边有个print()函数,作用是可以打印输出数据到控制台;CD和DVD是两个相似的类。
CD和DVD这两个类在定义的时候,使用关键字extends声明了其是Item类的子类,示例如下:

public class CD extends Item{
    //.....
}

则类Item属于cd和dvd的父类,它俩属于其子类,子类可以继承得到父类的所有的东西,包括数据成员、成员变量,同时对于子类,它自身也可以在继承得到父类的成员后自己再另外新增一些其他的成员。因为他们继承与父类,父类包含了一个print()成员函数,所以它俩可以不用另外构建相似功能的成员函数,直接可以使用从父类继承得到的这个函数。对于子类中所包含的类似的内容,其实我们提倡将他们都提取出来,放到父类中,这样代码只需要写一次,其他的子类就可以都继承得到了这些东西,这样可以提高代码的复用率,减轻后续的维护成本。但这会涉及到一些访问权限的问题,虽然子类从父类中继承了相应的成员,但这些成员仍然是父类的,父类的成员如果声明了private,那么子类就无法访问了。

子类与父类的关系

子类继承了什么?

父类的成员子类虽然继承了,子类中也有了相应的成员,但是不等于继承的成员就属于子类了,其仍然属于父类,在使用相关成员时,应该的访问方式是 父类.成员 的方式。如果父类将某些成员函数或者成员数据声明为private了,那么子类将无法访问了。解决方式是将声明改为protected,父类可以访问,同一个包内的其他类也可以访问,子类可以访问。
对于父类中的私有成员数据,如果需要对它进行一些操作,例如初始化,可以将操作方法写在父类中,无需写在子类中。如果需要子类传递参数进行一些操作,可以在子类中使用super()函数完成传递。
对于子类,他们在进行初试化的时候会先保证父类的构造函数和成员数据完成了初始化,然后才会来初始化子类的数据成员和构造函数,无论是否有super()都会如此,没有super()则会优先调用父类中没有参数的那个构造器,如果有参数,则调用带有形参的构造器(重载函数)。

子类和父类的关系

如果子类中存在与父类名称一致的成员变量,那么在子类中,父类那个相同名字的变量就会被隐藏起来了,在子类中针对这个变量的操作,指的是针对子类的变量进行操作,但是当我们回到父类中对这个名字的变量进行操作的时候,这时我们操作的变量是父类自己的变量。
父类的东西都继承给了子类,子类都得到了。但是那个东西如果是私有的,子类就不能碰,可以通过父类的函数去操作。成员在哪个类中被声明了,那这个成员就是哪个类的。如果父类和子类均有名字一样的成员变量,则他俩的这个同名成员变量互不相关。