本文目录一图览
立马开始学习
想学一个语言,至少要了解他是干嘛的,是什么类型的,创始人是谁什么的等等等乱七八糟的,对写代码作用不大,但是作为一个程序员必须要知道的东西。
下面的篇幅,字比较多,但是还是认真的看看吧,如果实在不愿意,那么只看粗体字就行了
当然了,事先声明,由于我是个初学者,如果有哪里不对的地方,希望各路大佬指出来,防止我和看我文章的人误入歧途,谢谢
首先呢,我们必须知道的是这个:Java 是由 Sun Microsystems(简称为sun公司,现在已经被oracle收购) 公司于 1995 年 5 月推出的高级程序设计语言,是面向对象的编程语言,用途广泛,可以做的方向很多。
然后呢,我们还必须要知道我们所学的编程语言的优点是什么
1. 一次写成,多次运行。 另一个名字是跨平台性。那么我们应该怎么理解呢,暂时打个哑谜,下面会介绍的,清耐心看下去哦!
2. 简单易用。 是的没错,简单易用!为什么呢,这里的简单易用是相对于C语言来说的,因为Java含有类和对象的概念,可以规避某些重复的代码,减少代码量。
3. 安全可靠。 Java通常用于网络环境中,为此,Java提供了安全机制以防恶意代码的攻击。Java程 序运行之前会利用字节确认器进行代码的安全检查,确保程序不会存在非法访问本地资源 和文件系统的可能,保证了程序在网络间传送的安全性。
4. 多线程。 Java支持多线程,可以使程序并发进行,在硬件条件允许的情况下,这些线程可以直接分布到各个 CPU 上, 充分发挥硬件性能,大大提升了程序的运行速率;利用Java的多线程编程接口, 你可以方便地写出多线程的应用程序。Java语言提供的同步机制可保证各线程对共享数据的正确操作。
Java 可运行于多个平台,如 Windows, Mac OS 及其他多种 UNIX 版本的系统,这是因为由Java虚拟机来完成的。
Java的按照用途来分,有三个版本,分别是JavaSE(Java标准版),JavaEE(Java企业版),JavaME(移动版)
那么到这里呢,你已经对Java有了一定的了解,但是呢随着你了解了一点,还是会产生更多的疑惑,那么随着我来慢慢学习吧,如果你还是不理解,那么
名词 | 解释 |
---|---|
JavaSE | 标准版,是为开发普通桌面和商务应用程序提供的解决方案 |
JavaEE | 企业版,是为开发企业级应用程序提供 的解决方案 |
JavaME | 微型版,是为开发电子消费产品和嵌入式设 备提供的解决方案 |
现在JavaME已经被Android代替 | |
JDK | Java开发工具包,Java的核心 |
含Java编译器、Java运行环境、Java打包工具、Java文档生成工具等 | |
JRE | Java运行环境 |
SDK | 软件开发工具包,开发Android必须有这个 |
javac.exe | Java编译器,将代码编译成字节码 |
java.exe | Java解释器 ,将字节码解释成机器语言 |
javadoc | 生成一个注释文档,和使用说明书一样作用 |
jvm | Java虚拟机 |
OK,相信现在大家就已经下载好了,那么我们就开始愉快的安装了
这是下载好的样子,双击
然后是这样子,点击下一步
这里可以选择安装路径,不过推荐还是默认安装位置,下一步
然后会看到文件下载,比如这样
然后下载完是这样,到这里就已经安装成功了
不过,不要急,还没完,相信你们内心都是这样,哈哈
不过不要急嘛,慢慢来,以后写代码会有很多的,有好多的,急可是不行的
其实如果使用全家桶系列的ide的话,这个环境配置是没有必要的,但是嘛,虽然没有必要,但还是要学的
2.1 首先找到你安装jdk的目录,也就是这个地方
2.2 打开bin目录
2.3 复制路径ctrl c
2.4 此电脑,右键,属性
2.5 高级系统配置
2.6 环境变量
2.7 新建系统变量
2.8 变量名为 CLASSPATH,变量值为 .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar 注意不要把**.**忘记
2.9 变量值为 JAVA_HOME,变量值为 你刚刚复制的路径
2.10 找到path,点进去,点击新建将“ %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;“填入
然后,就结束了,接下来让我们去试试是否成功安装了 Java
win+R 输入cmd
然后输入javac,回车
如果出现这种情况,就是成功了
如果出现javac不是内部或外部命令,也不是可运行的程序
或批处理文件那么就是你上面哪一步出错了,建议在好好看看,加粗字体不能错
我这边是在C盘新建了一个Java代码文件夹,点进去,新建一个文本文档
点进去,新建一个文本文档
命名为HelloWorld.txt,打开
把这个代码抄进去
public class HelloWorld{
public static void main(String args[]){
System.out.println("Hello World!");
}
}
Ctrl+s 保存
把文件名后缀改为.java
然后打开cmd命令行界面,输入cd \ 敲回车
然后cd java代码进入Java代码目录,输入javac HelloWorld.java
返回文件管理器,我们的Java代码界面可以看到多了一个HelloWorld.class的文件,这个是编译器将代码转为了字节码的格式,后面会详细说
然后回到cmd界面,输入java HelloWorld回车
然后就大功告成了,电脑返回给我们HelloWorld
我们的第一个Java程序就出来了,怎么样,有没有一种成功的快感
这款IDE可以说是非常的优秀,主要还是看着十分的炫酷,是由JetBrains公司开发的,隶属于此家的工具(我所用到的)还有pycharm,是支持python开发的一款很强大的IDE。下面是相关截图,包含社区版和专业版,社区版是免费的
IntelliJ下载地址:
1.官网下载
2.百度云盘下载 码:8dvo
是一款免费开源的现代化轻量级代码编辑器,支持几乎所有主流的开发语言的语法高亮、智能代码补全、自定义热键、括号匹配、代码片段、代码对比 Diff、GIT 等特性,支持插件扩展,并针对网页开发和云端应用开发做了优化。软件跨平台支持 Win、Mac 以及 Linux
vs code 下载地址:
1.官网下载
2.百度云盘下载 码:aode
EditPlus是一款由韩国 Sangil Kim出品的小巧但是功能强大的文本编辑器,小伙伴们可以使用EditPlus完成所有你想要的文本编辑功能。EditPlus也是一款非常好用的HTML编辑器,可支持C、C++、Perl、Java,EditPlus软件中有内建完整的HTML & CSS1 指令功能
(由于已经卸载,所以就不展示截图了。)
笔者初学Java的时候用的是IDE,后来到学校,老师是用EditPlus教的,再后来接触了VS code,现在学Android,Java只学基础语法就可以了,笔者推荐使用vs code,后面开发Android会用到AS Android Studio,是专业的Android原生开发工具,现在练习Java语法,使用vs code是够用的。当然,我们的代码演示都是以IDE来进行的,谁让我喜欢那个炫酷的界面呢
1.找到他并双击
2.next
3.这个地方可以更换安装地址,按照自己的需求和硬盘的大小安装
4.按照自己的需求勾选
5. 点击下载就行了
6.经过漫长的等待,终于是下载完成了,勾选这个
7.到这里社区版就安装好了,双击打开
8.这里没什么可说的
9.don‘t send
10. continue
11.选择样式,我更喜欢黑色的,下面选择安装一些插件(可以不选择,直接叉掉)
12.新建一个Java项目
13.选择jdk这个IDE一般会自动识别在哪里的
14.next两次
15. 这里面填写项目的名字,然后点完成
16.然后是这样1 2 3 按步骤走
17.创建一个包,com.项目名.作者名.名字,必须全部小写
18.按照步骤走,
19.创建一个Java类,首字母大写,其他单词首字母也大写
20.输入main,回车
21.写一个HelloWorld小程序(上一篇教过,应该都没忘吧)
22.右键,或者ctrl+shift+f10运行,
23.运行结果
24.大功告成,完结撒花
1.找到你下载的安装包双击
2.同意,下一步
3.该选择的选择,然后下一步
4.毋庸置疑,当然点击安装
5.安装完成
6.打开,点击这里
7.找到这个,点下载,我这里是禁用(因为我已经安装过一次)
9.创建一个新文件
10.调试为Java代码
11.把之前写的HelloWorld粘贴进去保存为HelloWorld.java文件
12.f5运行
会出现Hello World
每个编程语言都有各自的基本语法,代码风格等,你既然学这门编程,不仅仅需要知道怎么使用,还要知道怎么使用好
标识符就是变量、常量、方法、枚举、类、接口等 由程序员指定的名字。构成标识符的字母均有一定的规范
这么说可能有点难以理解,我就写段代码示例吧
package com.util.text; //包名,可以用.隔开,全部小写
public class HelloWorld{
//HelloWorld为类名
public static void main(String[] args){
//main为方法名
int girlFriend = 1; //变量
int GirlFriend = 2; //另一个变量
final int PI = 3.14; //常量名
String 9io = "ds"; //这种命名方法是错误的,复制代码的时候,记得把这一行注释掉
String $io,_io = "s","aa"; //正确命名不过一般不用$做第一个
System.out.println(girlFriend + $io + GirlFriend + PI + _io);
//输出的会是1 s 2 3.14 aa
}
}
关键字是由Java本身定义的单词,具有一定其他作用,比如class是定义类的关键字,int是声明整型变量的关键字,下面放一张关键字的图片
具体都是什么作用,这个,我暂时也没有研究完全,哈哈
保留字是Java语言中既不能当作标识符使用,也不是关键字,也不能在程序中使用,也就是不能在程序里面出现的单词
1. goto:在其他语言中叫做“无限跳转”语句,在 Java语言中不再使用goto语句,因为“无限跳
转”语句会破坏程序结构。在Java语言中goto的替换语句可以通过break、continue和return实现“有限跳转”。
2. const:在其他语言中是声明常量关键字,在
Java语言中声明常量使用public static final 方式声明
在Java源代码中,有一些字符被用作分隔,称为分隔符。分隔符主要有:分号(;)、左右大括号({})
Java中只使用英文符号,使用半角分号作为每行表达式语句的结束
System.out.println(""); //用半角分号作为这行表达式语句的结束
Java中使用大括号分割不同的代码块,比如不同类,不同方法,不同的控制语句
public class TheTect{
public static void main(String[] args){
//代码块
int a = 10;
if(a == 10){
System.out.println("000");
}
}
}
第一个大括号是分割类,第二个大括号是分割方法,第三个大括号是分割条件控制语句
变量应该先声明在定义,再使用,变量名命名规范上面有
我们应该先声明她的类型
按照这个格式去做 类型 变量名 = 值; 不要忘记以半角分号结尾
假如我们想定义一个名为helloWorld的字符串"Hello World!",我们需要这样做
String helloWorld = "Hello World!";
//定义一个常量 需要使用final关键字
final int S = 10;
Java中含有三种注释格式
使用 // 去注释
//这是单行注释
使用
/*
xxxxxx
*/
注释xxxxxx
/**
这里是
多行注释
*/
使用
/**
* 作者:xxx
* 日期:20210329
*/ 注释
可以使用javadoc生成注释文档
/**
* author: Smly
* data: 2021/3/29
* /
几乎与数学相同,先在脑子里搜刮一下关于数的数学知识
int a = 1;
long b = 1;
byte c = 1;
short d = 1;
System.out.println("int类型:"+ a +"\n" +"long类型:"+ b +"\n" +"byte类型:"+ c +"\n" +"short类型:"+ d);
/* 输出以下结果:
int类型:1
long类型:1
byte类型:1
short类型:1
*/
表示单个字符,定义时必须使用英文单引号\' '
```java
char a = ‘a’;
```
float a = 1.0f;
double a = 1.0;
在Java语言中声明布尔类型的关键字是boolean,它只有两个值:true和false
false
true
boolean isOK = true;
boolean noOK = false;
除了基本类型以外的都是引用数据类型
我觉得这个不用详细说,以后会有专门的章节细细讲到
类似于抽象类,以后会在面向对象的知识点细细讲解
数组就是一个存储多个数据的东西
//定义一个长度为10的整型数组
int[] a = new int[10];
//定义一个字符型数组
char[] ch = {
'a', 'b', 'c','d'};
//两种定义数组的方法,一种是定义长度,一种是直接定义
String a = "asd";
Java中变量定义时,先根据指定的类型分配一个内存地址,再将值放入其中
Java编译器将程序员写的Java源代码编译成字节码,然后通过Java解释器,转成二进制代码的格式交给计算机识别
想必各位都对这个并不陌生,什么+ - * / 的,大家都在数学中见过,但是还是有些不一样的地方的,那么跟着我来认识一下我们在Java中经常会见到的以后的熟人吧
运算符也有挺多类别,如常见的算术运算符,赋值运算符,逻辑运算符等,Java中有六种运算符:算术运算符,关系运算符,位运算符,赋值运算符,逻辑运算符,其他运算符
顾名思义,是用来进行运算的,有+,-,*,/,++,–,%
+ 的作用是进行加法运算,这个应该上过小学的人都知道,那么来看看Java中是如何使用的吧
public class Te0{
public static void main(String[] args){
System.out.println("1 + 1 = " +(1+1));
}
}
//输出的结果是 : 1 + 1 = 2
//2是运算结果,1+1=是字符串,不进行运算
- 的作用是进行减法运算,下面看代码演示
public class Te1{
public static void main(String[] args){
System.out.println("1 - 1 = " +(1-1));
}
}
//输出的结果是 : 1 - 1 = 0,0是运算结果,1 - 1 = 是字符串,不进行运算
* 进行乘法运算,下面看代码演示
public class Te2{
public static void main(String[] args){
System.out.println("2 * 3 = " +(2*3));
}
}
//输出的结果是 :2 * 3 = 6,6是运算结果,2 * 3 = 是字符串,不进行运算
/ 进行除法运算 5/4的结果默认是 1
public class Te3{
public static void main(String[] args){
System.out.println("5 / 4 = "+(5/4));
}
}
//输出的结果是 :5 / 4 = 1,1是运算结果,5 / 4 = 是字符串,不进行运算
之所以5/4的结果是1,是因为,这些数字是默认为整型的运算结果自然也是整型
% 是取余运算符,意思就是,拿到余数
public class Te4{
public static void main(String[] args){
System.out.println("3 % 2 = "+(3%2));
}
}
//输出的结果是 :3 % 2 = 1,1是运算结果,3 % 2 = 是字符串,不进行运算
++ 自增运算符,自己给自己加1 --(两个减号),自减运算符,单目运算符,只能适用于变量
public class Te5{
public static void main(String[] args){
int a = 1; //想使用单目,必须有变量
a++; //等效于a=a+1,但是输出的话,输出的是后面的a,而不是前面的
System.out.println(a);
//结果是2
/*
可能还是很不理解,那么久来看看这个例子吧
现在你叫张三,我给你个代号是a
a++就是,我对你说:张三,以后你叫李四,我先喊你的名字,然后告诉你,你名字被我改成李四了
++a就是,我直接在你档案改了你的名字,所以我喊你,应该喊李四,而不是张三
a--,--a同理
*/
}
}
顾名思义,就是计算你们两个的关系的,关系运算符有:== 、!=、>、<、<=、>= 这里的都是英文符号,需要注意的是,关系运算符都是二目运算符,返回的都是布尔类型的数据true/false
位运算符主要针对的是二进制数据,并只适用于int ,short ,byte,long,char五种类型。
位运算符有,&、|、<<、>>、<<<、^、~
既然有运算符,那么怎么能没有与或非呢,三种运算符:&&、 ||、 !
估计很多人都疑惑,为什么==是数学中的=,那么Java中的=是什么意思的呢?当当当当,就是这个赋值运算符了。当然,赋值运算符也是挺多的,不止一个=:=、+=、-=、*=、/=、(%)、<<=、>>=、&=、|=、^=,这里需要注意的是,这些赋值运算符都是双目运算符
int a = 1;
String _007 = "张三";
String _008 = "李四";
包含循环控制语句和条件控制语句
今天学到了个新知识,在学习一个东西前,先提出自己的一些问题,然后在学习,可能效率会高一点,那么就来提出一些问题吧
循环控制语句在于循环,能够让你在进行重复的操作时省时省力
举个例子:让你从1数到100,你数出来,会花费不短的时间,但是你让计算机数的话,计算机很快就能给你数出来,甚至可以说是瞬间
这个例子可能不太恰当,那么就来一个更加容易理解,也是学循环控制语句被玩烂的东西:1累加到100。让你手动算的话,要花费很多时间(不要跟我说什么你会数学,也能很快算出来,咱这边先不考虑,只是举个例子),但是让程序去用循环控制语句算的话就很快,也是瞬间。
for循环,由关键字for开头的
for(初始化;表达式;更新){
代码块
}
while循环,由while关键字开头的
while(表达式){
代码块
}
do…while循环,由do开头,中间由while衔接的
do{
代码块
}while(表达式);
通过例子,帮助理解
public class 循环 {
public static void main(String[] args) {
int num = 0; //声明一个用来接收累加结果的变量
for (int i = 0;i<=100;i++){
num = num + i;
}
System.out.println(num);
}
}
for循环直接在for后面跟初始体(int i = 0),限制条件(i<=100)和更新体(i++),中间需要用半角分号隔开,这是不可更改的
这个代码的意思是:初始化i是0,限制i的最大值是100,每次进行将num+i的值赋值给num循环后,让i+1。循环100次。结果是5050。
public class 循环 {
public static void main(String[] args) {
int num = 0;
int i = 0;
while (i<=100){
num = num + i;
i+=1;
}
System.out.println(num);
}
}
while循环里面的初始体需要在循环外面定义,更新体在循环内部,限制条件在while后面的括号里。
public class 循环 {
public static void main(String[] args) {
int num = 0;
int i = 0;
do {
num = num + i;
i+=1;
}while (i<=100);
System.out.println(num);
}
}
do…while循环,先执行do后面的代码块,再进行更新体的更新
循环我们已经知道了,那么嵌套循环是什么?
嵌套循环就是循环里面还有循环,用前段时间的网络用语就是循环套娃,当然,嵌套循环在生活中也是非常的常见的,比如:你要围着操场跑三圈,,每一圈都要跑多少步。跑三圈就是一个大点的循环,那么你跑一圈要多少步就是多少个小循环。那么代码表示大概就是这样:
用代码将:跑三圈 ,每圈4步 表现出来
public class ForExample{
public static void main(String[] args){
for (int i = 1;i<=3;i++){
System.out.println("第"+i+"圈");
int j = 1;
while (j<=4){
System.out.println("迈左脚");
System.out.println("迈右脚");
j++;
}
}
}
}
这个是for里面嵌套了一个while循环,外部循环一次,内部循环四次;意思就是按顺序循环,外面第一次循环,然后进入内部进行执行,进入内部又碰到循环,在里面需要把内部循环循环完成才能进行外部循环的第二次循环。这个代码循行的结果是:
/*
第1圈
迈左脚
迈右脚
(循环四次)
第2圈
迈左脚
迈右脚
(循环四次)
第3圈
迈左脚
迈右脚
(循环四次)
*/
//不展示那么多,免得说占字数
如果把这个理解了,那么可以尝试一下各种循环互相嵌套。
分别使用三个循环进行99乘法表的实现
条件控制语句用人的话来说就是,如果…就…
这么一听的话,是不是就觉得很简单了,那么去看看他怎么在代码中显示吧,不过在此之前,我们先去复习一下循环控制语句的小练习吧。
我们会在这里说明最简单的if语句,帮助理解if语句。
if(条件){
代码块
}
为什么说最简单呢,因为她只有一个if,没有别的了,意思就是,如果这个条件正确,就执行下面的代码块。如果错误,就跳过,条件的值必须是布尔值。比如:如果我十八岁了,我就可以去网吧上网。如果就是Java代码中的if,我是否十八岁是括号里面的条件,就可以去网吧上网是代码块。
int age = 18;
if (age>=18){
System.out.println("可以去网吧上网");
}
是不是很简单,这个时候,我们可以这样做:
String text = "理解";
String me;
if (me == text){
System.out.println("就这");
}
看懂的掌声,啪啪啪啪啪~~
这次我们的if有了个跟班,名字叫做else,大家应该都学过英语,都知道是什么意思吧。没错,其他。
我们if…else…的格式是这样的:
if (条件表达式){
代码块;
}else{
代码块;
}
上面已经说过,条件的值是布尔类型的,只有两个值,true和false,那这个的意思就是,如果条件是true,那么就执行if下面的代码块,如果是false就执行else下面的代码块。
明天是周末,假如我们计划:如果明天不下雨,那么我就出去跑步,如果下雨,就在家里读书。那么用代码写出来,应该不是很难吧
String weather = "不下雨";
if (weather == "不下雨"){
System.out.println("出去跑步");
}else{
System.out.println("在家读书");
}
上面哪一种是只考虑了两种情况,但是有时候往往两种情况是不适用于我们的实际运用的,比如说成绩,60以下是不及格,60-80是及格,80-100是优秀,这就有了三种情况,用if…else…就不行了,而我们的if…else if…else 语句应运而生。
语句格式:
if(表达式){
代码块;
}else if(表达式){
}else{
代码块;
}
下面我们就对这个成绩进行划分
int score = 80;
if (score<60&&score>=0){
System.out.println("不及格");
}else if (score>=60&&score<80){
System.out.println("及格");
}else {
System.out.println("优秀");
}
}
当然,还能有更多的情况,更多的情况就是更多的else if
条件控制语句,我觉得就是限制住某个条件才能执行,而嵌套的if就是在限制了一个条件后,再进行一次限制。
比如我们上面的划分成绩的例子中,我么后在对60-80的同学进行限制的时候,是用了我们说过的逻辑运算符,与,这个我们也可以使用嵌套来做。
下面看看用代码显示吧。
int score = 81;
if (score>=60){
if (score<80){
System.out.println("及格");
}
}
}
当然这个只是最简单的,我们就用嵌套把3中的第一个限制条件也改了吧
int score = 1;
if (score<60){
if (score>=0){
System.out.println("不及格");
}
}else if (score<80){
if(score>=60){
System.out.println("及格");
}
}else {
System.out.println("优秀");
}
学习语法嘛,要先看怎么用的,也就是,格式
switch(表达式){
case 值 ://语句
break; //可选
case 值 ://语句
break; //可选
//你可以有任意数量的case语句
default : //语句 //可选
}
嚯,这一看,不得了:这是什么玩意啊?
不慌,我们先看看怎么用的,就用猜拳游戏当例子吧
import java.util.Random;
//导入Random包,用于取随机数
import java.util.Scanner;
//导入Scanner包,用于从键盘获取数据
public class 猜拳 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); //只有sc是自定义的,别的地方都是固定语法
Random ra = new Random(); //固定语法
System.out.println("请输入你猜拳的数!规则如下:");
System.out.println("0——————石头");
System.out.println("1——————剪刀");
System.out.println("2——————布");
int a = sc.nextInt(); //用a从键盘接受一个整形类型的数据
int pc = ra.nextInt(2); //用pc变量接受一个从0 1 2 中随机取的数
String guiZe = null; //初始化变量
String pc1 = null; //初始化变量
switch (a){
case 0: guiZe = "石头";
break;
case 1: guiZe = "剪刀";
break;
case 2: guiZe = "布";
break;
}
switch (pc){
case 0: pc1 = "石头";
break;
case 1: pc1 = "剪刀";
break;
case 2: pc1 = "布";
break;
}
if (pc == a){
System.out.println("平局!");
System.out.println("你出的是:"+guiZe);
System.out.println("电脑出的是:"+pc1);
}else if (pc >= a){
System.out.println("你输了!");
System.out.println("你出的是:"+guiZe);
System.out.println("电脑出的是:"+pc1);
}else {
System.out.println("你赢了!");
System.out.println("你出的是:"+guiZe);
System.out.println("电脑出的是:"+pc1);
}
}
}
好,以上就是代码了,一眼看过去不会还是这样的感觉吧?(woc,这是什么鬼?)这都学到这里了,是时候该自己看代码了。——无良作者,什么时候学过Scanner和Random的,明明没有,掀桌 凸(艹皿艹 )
Random包,用于取随机数
Random ra = new Random();
ra.nextInt(2);
Scanner包,用于从键盘获取数据
用法:
Scanner sc = new Scanner(System.in);
sc.next类型();类型首字母必须大写
好,话外语已经说完了,继续我们的switch,既然代码那么长,就是看switch的部分吧
switch (a){
case 0: guiZe = "石头";
break;
case 1: guiZe = "剪刀";
break;
case 2: guiZe = "布";
break;
default: guiZe = "不符合规则";
}
switch (pc){
case 0: pc1 = "石头";
break;
case 1: pc1 = "剪刀";
break;
case 2: pc1 = "布";
break;
}
这个看着蛮复杂的,其实也算是个条件控制语句,我们先看第一个,其实只看第一个也就行了,开整,冲
如果a的值和case后面的值相等了,那么就执行冒号后面的代码,而如果没有相等的,就执行default后面的代码。好,我觉得我说的很详细了,就不多说了!
我觉得
好吧,还是有必要多说几句的
表达式的值可以是:byte、short、int 、char、String,且case标签必须是字符串常量或字面量
好了,这次是真的没了!
本来是不想说的,但是看很多人都没发现,还是说一下,文中的猜拳小游戏有些逻辑上的错误哦,由于懒(确实是懒,不是理由哈哈),错误是什么我就不说了,自己找吧,就当锻炼一下自己,当程序员,找错是必不可少的技能,冲冲冲
判断一个数(由自己定义)是否是质数
什么是质数:只能被1和他本身整除的数就是质数。 例如:2、3、5、7、11、13…
首先先分析分析怎么做到,我们知道,循环是连续执行的,那么怎么让程序将九九乘法表展示给我们呢?我们先回顾一下九九乘法表长什么样子
回想一下我们的循环,再结合这张图,我们能想到什么呢?第一行,只有一个,第二行,两个,第三行,三个…
我们可以用嵌套循环,外部循环表示纵的,内部循环表示横的,第一次循环,只输出1*1=1,只循环一次,第二行循环2次。。。做为限制条件,横的有9行,外部循环就以9为限制条件,那内部循环用什么呢,用纵列和行数的关系做为限制条件,就行了,代码如下
public class Te0 {
public static void main(String[] args) {
for (int i = 1;i<=9;i++){
for (int j = 1;j<=i;j++){
System.out.print(j+"*"+i+"="+(i*j)+" ");
//这个地方注意要用print,这个函数的意思是输出完不换行
//后面加空格是不让每个都连在一起
}
System.out.println(" ");
//这句的作用是,每次循环结束后,换行
}
}
}
结果:
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
先回顾一下题目:
判断一个数(由自己定义)是否是质数
什么是质数:只能被1和他本身整除的数就是质数。 例如:2、3、5、7、11、13…
想必对大家来说这个是很简单的吧!
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
boolean isPrime = true;
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个正整数");
int num = sc.nextInt();
if (num > 0) {
int k = (int) Math.sqrt(num);//k为num的正平方根,取整数
// 考虑平方根是为了减少重复量,开平方后面的数不处理
/*
素数是因子为1和本身, 如果数c不是素数,则还有其他因子,其中的因子
假如为a,b.其中必有一个大于sqrt(c) , 一个小于sqrt(c)
所以m必有一个小于或等于其平方根的因数,那么验证素数时就只需要验证到其平方根就可以了
*/
for (int i = 2; i <= k; i++) {
if (num % i == 0) {
isPrime = false; //不是素数
break;
}
}
}
if (isPrime) {
System.out.println(num + "是素数");
} else {
System.out.println(num + "不是素数");
}
}
}
就不多做赘述了
Java中有一些比较常用的类可以使用,今天就去学习一下# 关于数学的类Number类和Math类,一个是将内置数据类型装箱成对象,一个是进行数学中的相关运算
虽然Java语法中有着基本数据类型,但是有的时候我们在使用中,往往需要将数据作为对象来使用,所以Java中将数字的int、short、long、float、double、byte这几种内置数据类型都封装进类中,分别是Integer、Short、Long、Float、Double、Byte而他们都是Number类的子类,继承自Number类。
并且由于这些类都用了final修饰词修饰,所以是无法被继承,重写的。(继承这个后面会讲,大概意思就是父类有的,子类也有,父类没有的,子类也可以有)。
而关于基本数据类型的包装类,还有两个,一个是Character类,另一个是Booleam类。Number类在java.lang包中,包括它的子类也在java.lang中。这种由编译器特别支持的包装称为装箱,所以当内置数据类型被当作对象使用的时候,编译器会把内置类型装箱为包装类。
相似的,编译器也可以把一个对象拆箱为内置类型。
使用方法上和内置还是数据类型没什么区别都是先写类型名/类名+空格+变量名+赋值运算符+值+半角分号,以Integer为例:
public class Te0{
public static void main(String[] args){
Integer a = 10;
b= a + 10;
System.out.println(b);
}
}
运行结果
20
别的类也是同样的用法
Java 的 Math 包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数等运算,由于Math类是静态类(static),所以其中的方法可以直接调用,同样的Math类也不需要导入可以直接使用。
我爱数学,大爱数学
既然是用于数学运算的类,那么就不得不提一下两个量,一个是 π \pi π (圆周率3.1415926…),一个是e (自然常数)。
在Math类中,也有这两个量,使用final修饰,表示不可变的常量
π \pi π 在Java的Math中是Math.PI
e 在Java的Math中是Math.E。
public class Te1{
public static void main(String[] args){
System.out.println(Math.PI+" "+Math.E);
}
}
输出结果:
3.141592653589793 2.718281828459045
话不多说,咱就直接上干货!(干货?!真的是干货吗?作者竟然能写干货,稀奇)
Math.abs(-10); //结果:10
Math.ceil(5.2); //结果:6.0 直接让个位+1
Math.floor(5.7); //结果:5.0 直接让个位-1
Math.max(5, 6.2); //结果:6.2 比较两个数的大小,返回大的
Math.pow(2, 3); //结果:8.0 返回2**3的结果,结果为double类型
Math.random(); //结果:一个0-1的随机数,注意里面没有参数
Math.ronud(11.1); //结果:11
Math.sqrt(2); //结果:1.4142135623730951
简单的将方法叭叭后,就要动手练练?或者说是看一下运行结果?对,来了。
System.out.println(Math.sin(Math.PI/2)); //结果:1.0 求正弦值
System.out.println(Math.cos(Math.PI/2)); //结果:6.123233995736766E-17 求余弦值
System.out.println(Math.tan(Math.PI/2)); //结果:1.633123935319537E16 求正切值
System.out.println(Math.asin(0.5); //结果:0.5235987755982989 求sin的反函数值
System.out.println(Math.acos(0.5)); //结果:1.0471975511965979 求cos的反函数值
System.out.println(Math.atan(0.5)); //结果:0.4636476090008061 求tan的反函数值
总共这几种:String 、StringBuffe、 StringBuilder三种String是无法修改的,当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。
StringBuilder和StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类
String str = "Hello World!";
String str1 = new String("Hello World!");
字符串拼接
使用+号拼接
System.out.println("Hello"+" "+"World"+"!"); //结果:Hello World!
使用concat方法
System.out.println("Hello ".concat("World!")); //结果:Hello World!
字符串格式化
就是通过某种符号,将字符串格式化输出,可以这么理解:如果我要使用的字符串有可变量,比如说我跑步的时候,每跑一圈都要喊一句:跑了x圈。那么我们就可以使用字符串格式化。
—— 有人会说,之前用的时候,不是用的+号吗?
—— 确实,可以使用+号,不过如果有多个量的话,+会不会显得有一点繁琐了呢?
所以我们学过以后就可以用格式化字符串的方法了,既显得逼格高,又好用,岂不美哉?
System.out.printf("He%slo Wo%sld! ", "l","r");
//第一种方法结果是:Hello World %s表示占位符,可以表示任何类型的
//同样的占位符还有%d ,表示数字的
System.out.println(String.format("He%slo Wo%sld! ", "l","r"));
//第二种方法结果是:Hello World!
字符串比较
System.out.println("a".equals("b")); //结果是:false
字符串按照元素找下标
System.out.println("appdata".indexOf("t")); //结果是:5 如果没有找到,则返回-1
字符串长度
System.out.println("appdata".length());
//结果是:7 返回字符串的长度
与String不同的是,StringBuilder类的对象是可变的,意思是什么呢,就是我们可以直接在原对象上进行操作,而不会生成一个新的对象。
StringBuilder是一个类,所以通过new关键词来实例化对象
StringBuilder s1 = new String("hello world"); //直接写字符串,进行初始化
StringBuilder s2 = new StringBuilder(5); //定义一个长度,不进行初始化
System.out.println(s1+" "+s2);
s1.append("12345");
s1.append("666");
System.out.println(s1+" "+s2);
/*
输出结果为:
1234512345666 12345
*/
字符串.append\(\); 一个参数在原字符串后面加新的内容,上面第一四步就是在空字符串上加12345
StringBuilder s1 = new StringBuilder("hello world");
s1.append("!");
System.out.println(s1);
//结果:hello world!
字符串.insert\(\); 两个参数
StringBuilder s1 = new StringBuilder("hello world");
s1.insert(10,"!");
System.out.println(s1);
//结果:hello world!
第一个参数为字符串下标,第二个为内容,将内容添加到下标前面
3. 字符串.delete() 两个参数;两个参数都是下标,第一个是起始下标,第二个是终止下标,将两个下标之间的内容删除。
StringBuilder s1 = new StringBuilder("hello world!");
s1.delete(0, 4);
System.out.println(s1);
//结果是: world!
StringBuffer类和StringBuilder类一样,对象都是可变对象。
StringBuffer s1 = new StringBuffer ("123");
// 实例化对象为s1,并初始化为123
StringBuffer s1 = new StringBuffer ();
//实例化对象为s1,并不进行初始化
StringBuffer s1 = new StringBuffer ("123");
s1.append("1")
System.out.println(s1); //追加1,输出:1231
s1.replace("1", "2")
System.out.println(s1); //将1替换成2,输出:2232
s1.insert(3, "2")
System.out.println(s1); //在下标为3的后面插入2,输出:22322
s1.delete(1, 2)
System.out.println(s1); /删除从下标为1到下标为2的值,输出222
就这么多了,不过开头我也说了,这都是基操,所以,就这样吧。
一个是控制输入的类,一个是随机数类
从键盘获取数据,位于java.util包下,使用需要先导入
先导入
import Java.util.Scanner;
再实例化
Scanner scan = new Scanner (System.in);
//为Scanner类实例化一个名为scan的类,用于接收从键盘获取的数据
使用
int a = scan.nextInt();
//声明整型变量a,将从键盘获取的数据存入a中,输入的时候必须为整数,否则报错
float b = scan.nextFloat();
//声明单精度浮点数变量b,将从键盘获取的数据存入b中,输入的时候必须为单精度浮点数,否则报错
char c = scan.nextChar();
//声明字符型变量c,将从键盘获取的数据存入c中,输入的时候必须为字符型,否则报错
String d = scan.next();
//声明字符串d,将从键盘获取的数据存入d中,输入的时候必须为字符串,否则报错
System.out.println(a+" "+b+" "+c+" "d);
//可以像使用普通变量一样去通过变量名调用他们
好了,没了,我会的就这么多了,学识短浅
随机数类,简单实用,真的超级简单的用法
Random rd = new Random ();
//第一种方法:实例化一个Random类对象
Random rd2 = new Random (10);
//第二种方法:根据种子值实例化一个对象
System.out.println(rd.nextInt()); //生成一个随机整型数
System.out.println(rd.nextDouble()); //生成一个0-1的双精度浮点数
//…还有别的,用法是next+首字母大写的基本数据类型名字,和Scanner接收数据的用法差不多
System.out.println(rd.nextInt(5)); //生成一个0-5之间的随机整数
System.out.println(rd.nextDouble()*5); //生成一个0-5的小数
差不多这就够用啊,就这样咯
什么是数组?在Java中,数组就是存储多个相同数据的集合,他们的内存地址是相邻的,所以可以通过数组取值。
这么说,是不是有点不好理解,那么这样呢?
我有一颗白菜,手拿着就能回家,那如果是十几颗呢?
我就可以用麻袋!麻袋!装进去,带回家!是的你要存的数据就是白菜,而这个数组就是你要用的麻袋~~~~~
麻袋中的白菜怎么拿出来我需要用的呢?
下标,Java中的下标是以0开始的,什么是下标,就是你从0开始查,查到某个你要的数据,查到几,下标就是几,就相当于,我在装白菜的时候,说“这是第0个白菜,这是第1个白菜…”,而他们也能听懂(别管他们能不能听懂,我说能就能,哈哈~~),等我需要哪一颗白菜的时候,喊一声,他就自己跳出来了
白菜可以是任意类型的,但是麻袋要和白菜必须是同样的类型
两种方法
直接定义法:直接把白菜装进麻袋a里
int[] a = {
1,2,3,4,5,6,7};
实例化对象定义,初始化大小:不知道有什么白菜,先拿一个知道大小的麻袋a,然后再往里面装白菜
int[] a = new int[10];
多种数据,多种数据,多种数据,重要的事情说三遍
多种,怎么办?一个一个往里面装~~
怎么一个一个装?这种重复的事情,当然交给循环来干了!
比如说我要把1-66装进去
int[] a = new int[66];
for(int i = 0;i<a.length;i++){
a[i] = i+1; //这就是我告诉白菜,你是第i个白菜
}
我要把名字叫做5的白菜从麻袋里面拿出来,怎么做?
想必你们也都看到了这个a[i],这个就是对麻袋a中叫做i的白菜进行操作~
代码接着上面的
System.out.println(a[5]);
//结果是6,为啥是6,因为我们的白菜是从1开始往里面装的,而名字是从0开始取的
如果想全部取出,也可以用循环选手哦!
如果我的白菜,有的老,有的嫩,我想分开装,怎么办?
我告诉你,你这没必要用多个麻袋装,你可以在麻袋里在放几个麻袋啊。
这叫做:多维数组(麻袋里面的白菜,换成了麻袋,然后麻袋里面的麻袋里面装白菜)
定义一个里面含有三个麻袋的麻袋,每个麻袋可以装4个白菜
int[][] a = new int[3][4];
先打开这个a[]大麻袋,再打开里面的a[0][]小麻袋,然后才能往里面放白菜
小麻袋也有名字,也是下标,我们要往麻袋里面的第一个小麻袋的第一个位置放一个名字叫做1的白菜,这样做:
a[0][0] = 1;
先往第一个小麻袋放,在往第二个小麻袋放…
for (int i = 0;i<a.length;i++){
for (int j = 0;j<a[0].length;j++){
a[i][j] = j;
}
}
将我们的数组输出就行了
System.out.println(Arrays.toString(a[0]));
System.out.println(Arrays.toString(a[1]));
System.out.println(Arrays.toString(a[2]));
结果是:
[0, 1, 2, 3]
[0, 1, 2, 3]
[0, 1, 2, 3]
我们可以使用Arrays类操作我们的麻袋
将指定的 int 类型白菜分配给指定 int 型麻袋指定范围中的每个元素
int[][] a = new int[3][4];
Arrays.fill(a[0], 5);
Arrays.fill(a[1], 5);
Arrays.fill(a[2], 5);
System.out.println(Arrays.toString(a[0]));
System.out.println(Arrays.toString(a[1]));
System.out.println(Arrays.toString(a[2]));
/*
输出结果:
[5, 5, 5, 5]
[5, 5, 5, 5]
[5, 5, 5, 5]
*/
按升序排序,从小到大
int[][] a = new int[3][4];
//随便给几个值
a[0][2] = 5;
a[1][3] = 3;
a[2][0] = 4;
System.out.println(Arrays.toString(a[0]));
System.out.println(Arrays.toString(a[1]));
System.out.println(Arrays.toString(a[2]));
/*
排序前:
[0, 0, 5, 0]
[0, 0, 0, 3]
[4, 0, 0, 0]
*/
Arrays.sort(a[0]);
Arrays.sort(a[1]);
Arrays.sort(a[2]);
System.out.println(Arrays.toString(a[0]));
System.out.println(Arrays.toString(a[1]));
System.out.println(Arrays.toString(a[2]));
/*
排序后:
[0, 0, 0, 5]
[0, 0, 0, 3]
[0, 0, 0, 4]
*/
比较数组中元素值是否相等。
不相等返回false
int[][] a = new int[3][4];
int[][] b = new int[3][4];
System.out.println(Arrays.deepEquals(a, b));
//结果:false
定义两个数组,一个用于存放学生学号,一个用于存放学生姓名,使用循环同时打印学号与姓名
很简单的一个题,想想怎么做。
定义就不说了,很简单的,如何将他们两个同时显示,其实也很简单,就看脑子转不转的过来圈。
public class Hello{
public static void main(String[] args){
// 先定义两个数组
int[] ids = new int[]{
1001, 1002, 1003, 1004, 1005};
String[] names = new String[]{
"张三", "李四", "王二", "麻子", "张武"};
for (int i=0;i<ids.length;i++){
System.out.println("姓名是:"+names[i]+"学号是:"+ids[i]);
}
}
}
编程语言有面向对象(Java,Python)和面向过程(C语言)之分,面向对象需要一些抽象的思维才行。
面向过程和面向对象有什么区别呢?
面向过程注重亲力亲为,意思也就是自己去干这件事;而面向对象更倾向于找个人给自己做事。
就拿那个老生常谈的例子来说吧——洗衣服:
面向过程的洗衣服是每次洗衣服都需要:
等下一次洗衣服,你还得重复这些操作
而面向对象则是:
创造一个机器人
教他如何洗衣服
让他去干活
等下一次需要洗衣服,就让机器人去干,我们只需要歇着就行了
而面向对象绕不开的就是类和对象了,接着往下看吧
那么什么是类呢?类,分门别类的类,类别的类,人“类”就是我们现实生活中的一个类,而每一个人就是一个对象。
对象就是特殊个体,类就是一般个体,可能还是不那么好理解,我就再详细点
“我认识一个叫做丸子的女孩”——这句话中,丸子就是对象,代表一个真正的人,具体的人;而女孩就是类,代表一个抽象的东西,一个笼盖所有女孩的类别。
把具有相同特征的一些东西/事物分门别类,我们自己造一个名字
好,我们现在造一个火柴盒妹子类,用比较艺术化的话来说就是:只具其形,不具其神!
class Girl{
}
好了,这就是我们的女孩类,是不是感觉啥都没有,不对不对,Java类中有一个默认的东西,叫做构造方法,构造方法,构造方法,重要的事情说三遍!
构造方法:实例化对象时,自动调用,默认会存在一个无参数的构造方法
默认构造方法,只用于创建实例化对象,无法接受参数
public class Ec4_19 {
public static void main(String[] args) {
Girl girl = new Girl();
System.out.println(girl); //Girl@4517d9a3,返回的是内存地址
}
}
class Girl{
}
Java类中可以创建多个构造函数,但是参数和返回类型不能相同,这种情况叫做重载,意思就是你可以创建很多个构造函数
public class Ec4_19 {
public static void main(String[] args) {
Girl girl = new Girl();
Girl girl1 = new Girl("Jecy");
}
}
class Girl{
Girl(String name){
System.out.println("有参构造函数"+" "+name);
}
Girl(){
System.out.println("无参构造函数");
}
}
/*
输出结果为:
无参构造函数
有参构造函数 Jecy
*/
应该已经了解构造函数了吧,啊,这个实在想不出来什么骚话来形容~~
类中有属性,分为成员变量,局部变量和类变量
在我们创建的女孩类中,属性就是女孩们的诸如身材,相貌等的东西,当然,像什么年龄名字的,也是必须有的,不过不同的属性有不同的作用,所以属性也分上面三种
在类中,方法外定义,在实例化对象时创建,并可以被实例化对象拿去用(赋值,修改),不多说,看代码
public class Ec4_19 {
public static void main(String[] args) {
Girl girl = new Girl(); //实例化对象
girl.age = 10; //调用 设置成员变量值
girl.name = "Jeccy"; //调用 设置成员变量值
System.out.printf("%s今年%d岁了",girl.name, girl.age);
}
}
class Girl{
public int age;
public String name;
}
/*
输出结果为:
Jeccy今年10岁了
*/
在方法中定义,作用于在定义的方法中,也就是说只在该方法中能够使用,比如在构造方法中的变量,就无法通过实例化的对象调用
public class Ec4_19 {
public static void main(String[] args) {
Girl girl = new Girl(10,"Jeccy"); //用有参构造方法实例化对象
System.out.printf("%s今年%d岁了",girl.name, girl.age);
}
}
class Girl{
public int age; //成员变量
public String name; //成员变量
Girl(int a, String n){
age = a; //局部变量,无法通过实例化对象直接调用
name = n; //局部变量
}
}
/*
输出结果为:
Jeccy今年10岁了
*/
需要通过static修饰符修饰,可以直接通过类名调用
public class Ec4_19 {
public static void main(String[] args) {
Girl.name = "西施";
Girl.age = 10;
System.out.printf("%s今年%d岁了",Girl.name, Girl.age);
}
}
class Girl{
public static int age;
public static String name;
}
/*
运行结果:
西施今年10岁了
*/
无法被外界访问的属性,就是私有属性,就像女孩们有些东西不会被别人知道一样(比如三围之类的啦)
public class Ec4_19 {
public static void main(String[] args) {
Girl.name = "西施";
Girl.age = 10;
System.out.printf("%s今年%d岁了",Girl.name, Girl.age);
}
}
class Girl{
private static int age;
private static String name;
}
/*
这样写,就算是定义的静态方法,但是因为是私有的,也无法被访问
运行会报错
*/
行为就是方法,一般来说,Java类的规范写法是为每个属性设置一个setXxx方法,一个getXxx方法,并且将每个属性设为私有方法
就像这样:这是一般的规范写法
public class Ec4_19 {
public static void main(String[] args) {
Girl girl = new Girl();
girl.setAge(10);
girl.setName("Jerry");
System.out.printf("%s今年%d岁了", girl.getName(), girl.getAge());
}
}
class Girl{
private int age;
private String name;
void setName(String name){
this.name = name;
}
String getName(){
return name;
}
void setAge(int age){
this.age = age;
}
int getAge(){
return age;
}
}
当然,也有别的普通的方法,比如妹子会撒娇,会打游戏之类的
public class Ec4_19 {
public static void main(String[] args) {
Girl girl = new Girl();
girl.setAge(10);
girl.setName("Jerry");
girl.playGame();
System.out.println("");
girl.coqutry();
System.out.printf("%s今年%d岁了", girl.getName(), girl.getAge());
}
}
class Girl{
private int age;
private String name;
void setName(String name){
this.name = name;
}
String getName(){
return name;
}
void setAge(int age){
this.age = age;
}
int getAge(){
return age;
}
void playGame(){
System.out.printf("%s打游戏很厉害", name);
}
void coqutry(){
System.out.println("哥哥不要这样啦,人家害怕啦~~~");
}
}
/*
运行结果:
Jerry打游戏很厉害
哥哥不要这样啦,人家害怕啦~~~
Jerry今年10岁了
*/
继承就是我们的孩子,有我们造的妹子的特性,比如说:孩子长得像他妈妈啦,性格像她妈妈啦之类的
虽然在Java中,被继承的类叫做父类,但是我们也是可以这么理解的~
后面我就叫做母类了,emmm原谅我,我只是觉得这样更好听一点
当然,Java中,类的继承只支持单继承
public class Ex4_22 {
public static void main(String[] args) {
Child ch = new Child();
ch.setAge(10);
int age = ch.getAge();
System.out.println("孩子的年龄是:"+age);
System.out.println("孩子会撒娇");
ch.coqutry();
}
}
class Child extends Girl{
/*
孩子继承了妈妈的特性
*/
}
/*
运行结果:
孩子的年龄是:10
孩子会撒娇
哥哥不要这样啦,人家害怕啦~~~
*/
就是我们的孩子虽然已经继承了妈妈的东西,但是有些东西总不能是完全一样的
这个时候就要重写操作,可以将母类的东西改变,延伸
当然,我们的重写必须是跟母类的形参和返回值是相同的、、、
public class Ex4_22 {
public static void main(String[] args) {
Child ch = new Child();
ch.setAge(10);
int age = ch.getAge();
System.out.println("孩子的年龄是:"+age);
System.out.println("孩子会撒娇");
ch.coqutry();
}
}
class Child extends Girl{
public void coqutry(){
System.out.println("粑粑,我好爱你哦~~~");
}
}
/*
运行结果:
孩子的年龄是:10
孩子会撒娇
粑粑,我好爱你哦~~~
*/
重载是构造方法的重载,之前说过就不说了
还记不记得我之前说过的规范
一般将属性设置为private,私有类型,无法被外界的访问
而对于这样的属性,我们一般需要对每个属性设置两个方法,
一个是getXxx(), 一个是setXxx(),用于对属性初始化和调用
这个过程就是封装
class Girl{
private int age; //这个是年龄属性
private String name; //这个是姓名属性
public void setName(String name){
/*
设置名字
参数:name 名字
*/
this.name = name;
}
String getName(){
/*
获取名字
*/
return name;
}
public void setAge(int age){
/*
设置年龄
*/
this.age = age;
}
public int getAge(){
/*
获取年龄
*/
return age;
}
}
接口使用interface关键词来定义
interface Text{
//定义一个接口
}
接口是抽象方法的结合,被类继承
接口支持多继承(可以继承爸爸妈妈爷爷奶奶很多人的特性)
接口没有构造方法,因此无法进行实例化对象操作,只有在被类继承后,才可以继承用到接口中的方法
接口被类继承需要用到implements关键词
public class Ex4_22 {
public static void main(String[] args) {
Text_1 te1 = new Text_1();
te1.eat();
}
}
interface Text_0 {
int a = 0;
public void eat();
}
class Text_1 implements Text_0 {
public void eat(){
System.out.println("00");
}
}
//运行结果:00
抽象类并没有那么多属性可以去描绘一个完整的个体
public abstract class Ex4_22{
//定义一个抽象类
}
抽象类的方法也是抽象的,就是不具体的,就比如
我会说话,但是你只知道我会说话,而不知道我会说什么话,而这个会说话的方法就是抽象方法。
public abstract void print();//抽象方法,没有方法体,有abstract关键字做修饰
和接口不同的是,抽象类虽然无法实例化对象,但是抽象类是个类,有构造方法
所以抽象类一般在设计程序的时候就要考虑是否定义
而抽象类被继承后,继承抽象类的类需要将抽象类的抽象方法重写,使其具体化
public class Ex4_22 {
public static void main(String[] args) {
Text te = new Text();
te.print();
}
}
abstract class Ex4_2 {
//定义一个抽象类
public abstract void print();//抽象方法,没有方法体,有abstract关键字做修饰
}
class Text extends Ex4_2{
public void print(){
System.out.println("Hello");
}
}
//运行结果:Hello
Java 枚举是一个特殊的类,一般表示一组常量
比如妹子的性别等
使用enum定义
enum Gender{
MAN, WOMAN;
}
public class Test{
// 执行输出结果
public static void main(String[] args){
Gender c1 = Gender.MAN;
System.out.println(c1);
}
}
//运行结果:MAN
可以使用switch语句来使用
enum Gender{
MAN, WOMAN;
}
public class Ex4_22 {
public static void main(String[] args) {
Color myVar = Gender.MAN;
switch(myVar) {
case :
System.out.println("男性");
break;
case WOMAN:
System.out.println("女性");
break;
}
}
}
//运行结果:男性
枚举可以在类内部定义
在Java开发中,经常会遇到错误,这个时候就要学到异常处理,当然,学异常处理之前,我们应该先学学异常是什么~
异常就是我们在写代码的时候,爆红啦,高亮啦什么的,还有运行的时候碰到的各种报错啦
我们经常会因为各种各样的报错而头疼——哦!天呐!又报错了!
但是我们应该想想好的,我们编程水平不也随着解决各种各样的报错而提高了吗?
当然我们也可以通过某些方式来避免这种异常,当然这是我们在解决了许许多多的报错后的事啦,也就是现在!是的没错就是现在!O(∩_∩)O哈哈~
一般分为三个类型:编译时错误 、运行时错误 、逻辑型错误
就是在写代码的时候,出现了语法上的错误,比如在定义变量的时候
int i = 1
在这里,我们就犯了个编译时的错误,少打了一个作为每句表达式结束的英文分号
就是语法上没有出现错误,但是编译的时候会出现错误,比如
double[] a = {
1.0, 2.0};
System.out.println(a[3]);
在这里,虽然不会爆红,但是却会在运行的时候出现错误
Index 3 out of bounds for length 2
意思是索引超出范围,我们的数组只有两个长度,却查找第四个元素,很明显是不对的
就是我们的代码不符合逻辑
int a = 1;
int b = 0;
System.out.println(a/b);
就会出现错误
/ by zero
可分为Error和Exception两种,Throwable是Error和Exception的共同父类
Error为错误,是程序无法进行处理的
一般遇到错误,不应该使用异常处理try…catch…
而是修改源代码,进行改良
Error有三个子类:
目前我只见过内存溢出错误,通常是因为某些原因,程序出现死循环导致的
Exxception可以通过代码来避免,分成运行时异常和非运行时异常
运行时异常:RuntimeException
非运行时异常:IOException、SQLException、、
码代码的时候,编辑器不会给你提示,但是会出现错误
NullPointerException(空指针异常)
比如在定义了一个方法并使用的时候,传递的参数为空public class Ex4_26 {
public static void main(String[] args) {
Integer a = null;
Integer b = 1;
System.out.println(jiSuan(a,b));
}
public static Integer jiSuan(Integer a, Integer b){
Integer c = a + b;
return c;
}
}
报错了:
ArrayIndexOfBoundsException(数组下标越界异常)
我觉得我不用多说,看中文名字应该就知道这是个啥了,不过我还是大发慈悲的决定上代码public class Ex4_26 {
public static void main(String[] args) {
int[] a = new int[10];
System.out.println(a[10]);
}
}
会报错:
如果出现运行时异常,通常是程序员的问题,因为这些都是可以通过逻辑上的处理而避免
IOException(IO异常)、SQLException(SQL异常)
我们的程序遇到这种异常通常会直接结束,并会返回报错信息给你
如果我们想要让我们的程序继续运行,我们就需要通过代码对这些异常进行处理
try {
可能会遇到异常的代码块
}catch (){
遇到异常之后,会做的事情
}finally {
不管会不会出现异常都会进行的操作
}
public class Ex4_26 {
public static void main(String[] args) {
String[] a = new String[10];
try {
System.out.println(a[10]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println(e);
System.out.println("下标越界啦!");
}finally {
System.out.println("不管下标是否越界都会执行");
}
}
}
可以清晰地看到,我们的数组长度只有10,而下标是从0开始的,所以我们查看下标为10的元素的时候,就会出现数组下标越界异常,因此那行代码就是错的,不会被执行,会执行下面的代码
知道常见的集合
会集合的简单操作
特点: 存储空间可变
存储多个数据时,经常会遇到长度不固定的情况,此时,就无法使用数组进行存储,此时就需要用到集合
分为Collection和map
collection是集合,以每个元素分开储存在同一个集合
map是键值对的形式(什么是键值对?一个名字对应一个人就像这样:“z”: 1这样,"z"是键,1是值,合在一起就叫键值对)储存
set集合的元素是无序的
优点:删除和插入效率高,元素是无序的,不会引起其他元素的变化
缺点:查找效率低
举个例子方便理解:
set集合相当于是一个乱糟糟的大厅
你想在里面找某个人(查找元素),比较麻烦
但是你进去出来却不会引起什么变化
list集合是有序的,和数组类似,只不过list集合的长度是动态的
优点:查找效率高
缺点:插入删除操作效率低,会引起元素位置的变化
举个例子方便理解:
list集合就相当于一个标注着名字的会议室
你要找某个人,很轻松就可以找到
但是你要是想在里面加个座位给新来的领导,就会很麻烦
map使用键值对的形式储存数据,不算集合,但是在Java中却是整合在集合中的
ArrarList,LinkedList,HashSet,HashMap
当然,由于集合在java.util 包中,因此在使用之前应该先导包
import java.util.ArrayList;
ArrayList<类型> 变量名 = new ArrayList<>();
这里的类型只能是引用数据类型,如果想储存基本数据类型,可以装箱
常见方法,当然少不了增删改查
ArrayList.add("元素"); //在ArrayList最后面追加元素
ArrayList<String> b = new ArrayList<>();
for (int i = 0; i<10; i++){
b.add(Integer.toString(i));
}
System.out.println(b);
ArraysList.add(5, "在下标为5的位置追加引号中的内容");
ArrayList<String> b = new ArrayList<>();
for (int i = 0; i<10; i++){
b.add(Integer.toString(i));
}
b.add(5,"sja");
System.out.println(b);
ArrayList.remove(下标); //删除下标元素
ArrayList<Integer> b = new ArrayList<>();
b.add(1);
b.add(2);
b.add(3);
b.add(4);
b.add(5);
b.remove(3);
System.out.println(b);
运行结果:
ArrayList.set(下标); //通过下标修改元素
ArrayList<String> b = new ArrayList<>();
for (int i = 0; i < 10; i++) {
b.add(Integer.toString(i));
}
b.set(3, String.valueOf(10));
System.out.println(b);
运行结果:
ArrayList.get(下标); //通过下标访问元素
ArrayList<String> b = new ArrayList<>();
for (int i = 0; i < 10; i++) {
b.add(Integer.toString(i));
}
String a = b.get(3);
System.out.println(a);
}
运行结果:
链表是一种线性表,但是却不是按线性的顺序储存数据,而是每个节点里存到下一节点的地址(这个是不是不太好理解,下面详讲)
例子理解:
就相当于你去操场跳广播体操,每个人一小块地方,需要在指定时间內按照之前的顺序站好,你如果把那些小 块块都一个个排序好序号,然后再找,固然可以(这是数组的方法),但是也多多少少有点费事,而这个链表 就是让你记得站在你旁边的人的位置,而去找自己的位置
链表有单向链表和双向链表
单向链表:每个元素只记后面元素的位置,而不管其他
双向链表:不仅仅后面,还有前面
LinkedList和ArrayList相差不大,但是LinkedList的增删效率高,改查效率低
增删改查
LinkedList.add(); //往链表后面添加元素
LinkedList.addFirst(); //往链表开头添加元素
LinkedList.addLast(); //往链表末尾添加元素
//实操理解
LinkedList<String> te1 = new LinkedList<>();
te1.add("I");
te1.add("am");
te1.add("Smly");
System.out.println(te1);
运行结果:
//接上面的代码
te1.addFirst("hello");
te1.addLast("bye");
System.out.println(te1);
运行结果:
LinkedList.remove();
LinkedList.removeFirst();
LinkedList.removeLast();
不多做赘述
LinkedList.set(下标, 元素); //将该下标对应的元素修改
LinkedList.get();
LinkedList.getFirst();
LinkedList.getLast();
LinkedList.size(); //返回链表大小
HashSet是set集合,元素是无序的,并且不允许有相同的元素出现
HashSet.add(); //增
HashSet.remove(); //删
HashSet.size(); //大小
HashSet.contains(); //判断元素是否存在
代码展示:
HashSet<String> ha1 = new HashSet<>();
ha1.add("Hello");
ha1.add("world");
ha1.add("!");
ha1.add("。");
System.out.println(ha1);
Boolean cunZai = ha1.contains("a");
int dax = ha1.size();
System.out.println(cunZai+" "+dax);
ha1.remove("。");
System.out.println(ha1);
结果:
是map,键值对形式存储数据,可以自由规定键值对的类型
现在讲解使用键字符串,值整型来演示
HashMap.put(键,值); //增
HashMap.remove(键); //删
HashMap.get(键); //查
HashMap.size(); //大小
HashMap.clear(); //全部删除
代码示例:
HashMap<String,Integer> hama = new HashMap<>();
hama.put("Jerry", 13);
hama.put("Jack", 16);
hama.put("Tom", 18);
hama.put("TextClear", 11111);
System.out.println(hama);
hama.remove("TextClear");
System.out.println(hama);
int age = hama.get("Tom");
int size = hama.size();
System.out.println(age+" "+size);
hama.clear();
System.out.println(hama);
结果展示:
当我第一次听到这个东西的时候,我是这样想的:
泛型?什么东西,听起来感觉挺高大上的,我能学会吗?我能理解吗?我会不会栽在这里?
是啊,听起来就蛮牛,蛮高大上的嘛,但是你需要仔细理解,啊不对,说得简单点,你就把这俩字拆开来解读不就完事了吗?
泛型:
泛:广泛
型:类型
对,其实就是这样,是不是瞬间感觉
好嘛,这才哪跟哪啊,你要是这样想,就对了!哈哈,不要觉的他好难好难的
理解最重要,我一向反对死记硬背的学习,所以我也不抄别人的看着好高大上的解释,除了让人望而生畏之外,对理解并没有什么卵用。
像他们说的什么参数化类型,那玩意真的能让很多人理解吗?
并不能,至少在我看到这个的时候,是无法很清晰的理解到的,既然我做不到,那么根据某定理(想不起来名字了),那么肯定也有人和我一样,无法很明白的,很清晰的理解这个东西。
那我就按照我的理解来说了
那么我们先来看看这个代码
ArrayList<String> b = new ArrayList<>();
之前说过,哪个小小的尖括号里面是放类型的,可以是任意的引用类型
何为引用类型:字符串,数组,接口,类。。。
那么我需要整型的怎么办,之前也说过,装箱,装箱为Integer这种类型的就可以了
好,言归正传,这个代码我们很熟悉,创建一个ArrayList集合对象嘛,形式我们也很熟悉,类的实例化对象嘛。
但是你有没有发现,这个格式貌似和我们自己定义的类的实例化对象的格式不太一样?
那么再来看看我们之前创建的Girl类的实例化
Girl girl = new Girl();
大致一看,还是差不多的:
类名 自定义名字 = new 类名;
但是仔细一看就不一样了,尖括号,对,我们创建的Girl中没有尖括号。
那么这个尖括号是干嘛的呢?联想我们的这个博客,你是不是若有所思?难不成,这就是泛型?
对啊,这就是泛型啊,这就是Java中的具体使用,用来广泛特指别的类型
说到这里,有没有一种恍然大悟的感觉
泛型类型在逻辑上看成是多个不同的类型,实际上都是相同的基本类型
相信经过上面的解释,你已经对泛型有所理解,那么来看看我们怎么使用泛型吧
先来看看如何定义一个泛型类
class 类名<泛型类型(一般使用T,K,V,N,也可以使用别的)>{
public 泛型类型 变量名; //初始化一个泛型类型的变量
public 泛型类型 方法名(泛型类型 变量名){
代码块;
}
}
应该,很清晰吧,都是之前学过的东西了
那么来看看怎么使用的吧!
这次测试还是我们的妹子类
由于英文不好,主类名就用拼音了,见谅见谅
public class Fanxing {
public static void main(String[] args) {
Gril5_3<String> text = new Gril5_3<>("测试成功");
text.setT("hello");
String a = text.getT();
System.out.println(a);
}
}
class Gril5_3<T>{
private T t;
public Gril5_3(T t){
this.t = t;
System.out.printf("测试泛型ddd %s",t);
System.out.println();
}
void setT(T t){
this.t = t;
}
T getT(){
return t;
}
}
应该没什么问题吧,set和get用于封装,使用泛型类型替代了原来的类型,定义属性的时候也使用泛型类型替代
运行结果:
好好好,好啊,我们成功了!
那么需要注意的是,我们在实例化前,我们的类型T可以是任意类型的,意思就是,你定义是什么类型,他就是什么类型的。
通配符,就是字面意思,可以通用的符号
不得不赞一句,见名知意的感觉是真的好,以后我们写代码的类啦,接口啦,方法啦,一定要记得这样命名,见名知意!!!
一般用于集合中传递数据时
示例说明
public static void main(String[] args) {
Collection<Integer> list01 = new ArrayList<Integer>();
Collection<String> list02 = new ArrayList<Integer>();
Collection<Number> list03 = new ArrayList<Integer>();
Collection<Object> list04 = new ArrayList<Integer>();
}
// 定义方法 用于接收任意的数据类型
public static void getElement(Collection<?> coll) {
//.....}
// 定义方法 用于接收数字类型 Number类型或者Number的子类Integer等
pubic static void getElement(Collection<? extends Number> coll){
//...}
// 定义方法 用于接收Number类型及其父类的类型
public static void getElement(Collection<? super Number> coll) {
//....}
泛型就说这么多,相信大家对泛型也有了自己的认识,想去深挖的话,还是别来看我的博客
建议找大佬的博客钻研钻研一起进步一起学习!
什么是反射?就是Java中可以通过反射,将类的各个组成成分映射成一个个的对象。
好,这是我查看别人的解释。
那么现在就来说说我对反射的理解。
反射:
就是在你只知道一个类名,而且无法查看类的源码(也就是说你对这个类的理解只局限于你知道类名)的时候,可以通过反射来将类中的各个成分调出来,成为一个个对象,可以通过反射了解这个类的成分。如果你不知道类里面都有哪些成分的话,那说明你的基础还不够扎实,推荐你去看看我的类三部曲。
那么这么说还是有点不太容易理解吧。
那就举个例子:
我是一个黑客,有个人叫张三(类),他惹了我,我知道了他的名字(类名),我通过技术手段(反射)人肉到了他的个人消息(各个组成成分)。
这就是反射!
反射可以将加载到JVM中的类的信息加载出来,供我们使用。
反射在框架架构中经常使用,而在日常开发中,并不经常使用。
那么为什么我们还需要学习反射呢?因为我们需要去看别人的框架源码来深入学习,而如果我们对反射不理解的话,就不能理解别人的源码。
优点
缺点
使用反射技术,就不得不提一下Class类,下面我们先看看别人对Class类的说法:
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。也就是Java虚拟机中有N多的实例每个类都有该Class对象。(包括基本数据类型)
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。
——摘自Java基础之—反射(非常重要)
换句话说,我们所用到的所有类,都是Class类的一个实例化对象。是不是感觉有点难,没事,其实之前我听过一个底层大佬的一句话,感觉受益很多:
每个类都是更抽象的类的对象罢了
而我们现阶段不需要了解那么多,只需要使用Class类中的方法就可以了
好了,巴拉巴拉的说了这么多,也该上代码了
class Girl_5_5{
String name;
Integer age;
Integer ID;
public void describe(String name, Integer age, Integer id){
this.ID = id;
this.name = name;
this.age = age;
System.out.printf("我是%s,我的证明是%d,我今年%d岁了", name, id, age);
}
}
我们需要获取Class对象获取Class对象的三种方式
Object类(自定义类的默认父类)的getClass();方法
类自带的class属性 类名.classs;
通过Class类的静态方法:forName(String className)(常用)
public class Fanshe {
public static void main(String[] args) {
Girl_5_5 girl = new Girl_5_5(); //实例化一个对象
//第一种方法,使用所自定义类中的默认父类Object的class方法
Class<? extends Girl_5_5> girlClass = girl.getClass();
//第二种方法 访问静态属性class获取
Class<Girl_5_5> girlClass1 = Girl_5_5.class;
//第三种方法
try {
Class<?> girlClass2 = Class.forName("com.util.text.基础语法.反射.Girl_5_5");
System.out.println(girlClass+"\n"+girlClass1+"\n"+girlClass2);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class Girl_5_5{
String name;
Integer age;
long ID;
public void describe(String name, Integer age, long id){
this.ID = id;
this.name = name;
this.age = age;
System.out.printf("我是%s,我的证明是%d,我今年%d岁了", name, id, age);
}
}
运行结果:
这都是我们的Girl_5_5类对象,我们将这个类,通过反射实例化成了一个Class类的对象,可以通过这个对象调用Class的方法,通过Class的方法可以获得Girl_5_5的构造方法,成员变量等,并将其化为一个一个的对象。
所有构造方法:girlClass2.getDeclaredConstructors();
所有公有构造方法:girlClass2.getConstructors();
所有公有无参构造方法:girlClass2.getConstructor(null); 这个参数也可以不放
import java.lang.reflect.Constructor;
import java.util.Arrays;
public class Fanshe {
public static void main(String[] args) throws Exception {
Girl_5_5 girl = new Girl_5_5(); //实例化一个对象
//第一种方法,使用所自定义类中的默认父类Object的class方法
Class<? extends Girl_5_5> girlClass = girl.getClass();
//第二种方法 访问静态属性class获取
Class<Girl_5_5> girlClass1 = Girl_5_5.class;
//第三种方法 通过forName方法获取
try {
Class<?> girlClass2 = Class.forName("com.util.text.基础语法.反射.Girl_5_5");
//输出三种方法
System.out.println(girlClass+"\n"+girlClass1+"\n"+girlClass2);
//所有构造方法
String allConstructors = Arrays.toString(girlClass2.getDeclaredConstructors());
//所有共有构造方法
String publicConstructors = Arrays.toString(girlClass2.getConstructors());
//共有无参构造方法
String nullConstructors = Arrays.toString(new Constructor[]{
girlClass2.getConstructor(null)});
//输出看看
System.out.println(allConstructors+"\n"+publicConstructors+"\n"+nullConstructors);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class Girl_5_5{
String name;
Integer age;
long ID;
public void describe(String name, Integer age, long id){
this.ID = id;
this.name = name;
this.age = age;
System.out.printf("我是%s,我的证明是%d,我今年%d岁了", name, id, age);
}
/**
* 共有有参构造方法
* @param name:提供一个形参
*/
public Girl_5_5(String name){
System.out.println(name+"hello");
}
/**
* 共有无参构造方法
*/
public Girl_5_5(){
}
/**
* 私有有参构造方法
* @param age:提供形参
*/
private Girl_5_5(Integer age){
}
}
运行结果:
获取所有:girlClass.getDeclaredFields();
获取所有公有:girlClass.getFields();
具体我就不一一举例子了
获取所有:girlClass.getDeclaredMethods();
获取所有公有:girlClass.getMethods();
反射就是能在你只知道类名的时候,获取调用类的各种组成成分。
好嘛,好嘛,又到了伤脑筋的时候啦!
讲真的,之前Java这三大高级特性,我一听名字就感觉到了一股杀气!哇,泛型,反射,注解,这都是什么高级词汇,一听就很难学!
后来学了后发现,嗯,没感觉错,确实是很难学!哈哈哈(笑啥笑,难学还挺开心)
今天我们的主角是注解。好家伙,注解。啥东西啊,看着就没思路。
不要慌,问题不大
我们先看看比较官方的解释:Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。
看看官方解释,再结合字面意思,咦,貌似有点内个意思了哈。
上面清晰的写着,注解不直接影响你的代码执行,意味着什么,意味着我们从字面理解的意思,是差不多对的。
好,总结一下,注解就是:声明我们的代码中的方法,属性,类,接口等作用的,而且和注释不同的一个东西。
而且而且,貌似你可以这么理解,我给你一个注解,像不像我给你扣了一个大帽子。
比如说你初学Java,进了一个Java群,你刚好会了一个新知识,这时候有一个比较活跃的群友问了这个问题,你洋洋洒洒的说了出来,顿时这个人就给你套了个大佬的帽子,因为他是活跃群友,所有你一冒头他就喊你是大佬,这样你在别人眼里也就是大佬了。
而注解就相当于是我给代码套了个帽子,让别的程序员一下就能看出来他是干嘛的 。
Java代码中的注解就是这种形式的
在代码上面有个 : @Xxxx 的东西
应该见过,也可能没见过,不过就是这个东西,这是用法
那么怎么创造一个注解呢
其实特别简单,格式如下:
@Interface Xxx{}
没了,就这么简单
那么我们就动动小手 创建一个我们能的注解吧
//定义一个 什么都没有的 注解
@interface Isthis{
}
这就定义好我们自己的注解了
上面我们已经定义了一个注解,那么怎么使用呢
只需要将我们自己定义的注解(名词)放在我们需要注解(动词)的代码上面,就像这样
//定义一个 什么都没有的 注解
@interface Isthis{
}
//使用你的注解
@Isthis
class Good{
}
我们定义了一个空的注解,也定义了一个空的类,并将我们的注解用在了我们的类上面
当然,这样很不直观,那么我们就实例化一个对象来看看
public class Ex5_8 {
public static void main(String[] args) {
Good a = new Good();
System.out.println(a);
}
}
运行结果为:
然后再将注解去掉看看
public class Ex5_8 {
public static void main(String[] args) {
Good a = new Good();
System.out.println(a);
}
}
class Good{
}
运行结果为:
是一样的,说明注释对我们的代码没有影响
什么是元注解?能给注解进行注解的注解。
哈哈哈,是不是有点套。没事,这样看:
元注解是能给注解(我们之前定义的)进行注解(注释解释)的注解(名词,注解)。
这就很清晰了吧。
我们的元注解有以下几种,下面我将带领大家看看。
Retention的意思是保留。根据见名知意的理解,其实这个元注解的作用其实就是注解的保留时间,也就是这个注解能保留到什么时候。
注解也有方法,我们来看看这个保留注解的方法
被这个属性注解的注解,只在源代码中能看到,起作用
用法是这样:
@Retention(RetentionPolicy.SOURCE)
@Interface Text{
}
被这个属性注解的注解,在class文件中也可以看见,但是不会被我们的Java虚拟机加载
用法:
@Retention(RetentionPolicy.CLASS)
@interface Text{
}
会被Java虚拟机加载
@Retention(RetentionPolicy.RUNTIME)
@interface Text{
}
中文意思是:备有证明文件的。好吧,这个意思就不是那么清晰了
这个元注解的作用是将我们的注解加载到javadoc中,这个javadoc是我们的Java程序中所有的文档注释(/** */)产生的注视文档。
而这个元注解就是可以让我们的注解也进入这个文档。
中文意思是:目标。
作用是:告诉注解,你该用到哪里,就是说被这个注解的注解可以注解什么类型的数据
大白话:我告诉你,你只能给类进行注解,那你就只能给类注解,放别的地方就会报错。
具体使用如下:
可以给注解进行注解,是不是想到了元注解,没错,可以看看元注解的源码,都被这个注解过
@Target(ElementType.ANNOTATION_TYPE)
@interface Text{
}
可以让注解给构造方法注解
@Target(ElementType.CONSTRUCTOR)
@interface Text{
}
可以让注解给属性进行注解
@Target(ElementType.FIELD)
@interface Text{
}
可以让注解给局部变量进行注解
@Target(ElementType.LOCAL_VARIABLE)
@interface Text{
}
可以让注解给方法进行注解
@Target(ElementType.METHOD)
@interface Text{
}
可以让注解给包进行注解
@Target(ElementType.PACKAGE)
@interface Text{
}
可以让注解给方法变量进行注解
@Target(ElementType.PARAMETER)
@interface Text{
}
中文意思:继承
被此元注解 注解(动词) 的注解(名词),如果注解了一个类A,类A被类B继承,那么,类B同样继承类A的注解。
@Inherited
@interface Text{
}
@Text
class Good{
}
class Good_son extends Good{
}
这里的Good_son类虽然看起来没有被注解,但是因为Inherited元注解的存在,他也继承了Good的注解@Text.
标准注解就是直接作用在别的数据上的
什么是数据?变量,方法,类,接口,枚举。。。
中文意思:重写
保证Override重写声明的正确性。
是不是很眼熟,没错就是了类里面的重写父类方法,这个注解的作用就是用在子类需要重写的时候。
如果父类没有你要重写的方法,就会出错误。这里我们故意出错看看错误
class Good{
void say(){
}
void speak(){
}
}
class Good_son extends Good{
@Override
void say(){
}
@Override
void spea(){
}
}
idea的方便之处,会爆红:
会提示错误,并给出解决方法
意思就是,你的父类没这个方法,下面的上移就是讲这个方法在父类实现。
改正确,就不会爆红:
中文意思:不宜用
就是这个方法已经不适合使用了
public class Ex5_8 {
public static void main(String[] args) {
Good a = new Good();
a.say();
}
}
class Good{
@Deprecated
void say(){
}
void speak(){
}
}
这样看代码,不太直观,还是放idea的截图吧
say方法被@Deprecated注解,在实例化调用的时候,就会有删除线,意思就是,这个方法已经不适合使用了。
注解也有属性,和类一样。
用法是这样
@interface Text{
int id();
String value();
}
@Text(id=1, value="s")
class Good{
void say(){
}
void speak(){
}
}
定义注解属性的时候,类型 属性名();
属性可以有默认值,默认值需要用default关键字传递
类型 属性名 default 值
@interface Text{
int id() default 0;
String value();
}
@Text(id=1, value="s")
class Good{
void say(){
}
void speak(){
}
}
关于本篇,引用一个群大佬的话:
stream是管道,文件是数据载体,IO(InPut(输入)、OutPut(输出))是数据的流动的方向
Java流是对于字节和字符来说的,所以是字节流,字符流。
什么是流,大家看一个词,水流,什么是水流大家都知道,那么换成字节流,字符流不过是同样的意思罢了。
什么是字节流?单个字节或者字符,而单个字节或者字符很明显构不成流,得是多个字节或者字符。
那么这么解释,应该是不会再感觉到困惑啦。
下面看看实操吧。
咦,突然有种莫名的熟悉感。这不是Scanner吗!
不不不,今天我们讲的是另一个:InPutSteamReader
看着好长啊,我们这次先不去管它是什么,我们先看看他能干什么:获取键盘数据
import java.io.*;
public class Ex5_9io {
public static void main(String[] args) throws IOException{
BufferedReader a = new BufferedReader(new InputStreamReader(System.in));
//获取单个字符
char c;
c = (char) a.read(); //使用c来接收字符
System.out.println(c); //输出
}
}
运行结果:
玩点花的:
import java.io.*;
public class Ex5_9io {
public static void main(String[] args) throws IOException{
BufferedReader a = new BufferedReader(new InputStreamReader(System.in));
//获取单个字符
ArrayList<Character> c = new ArrayList<>();
for (int i = 0;i<10;i++){
c.add((char) a.read());
}
System.out.println(c);
}
}
都是之前学过的东西,如果你看不懂,说明基础大的不太牢固哦
运行结果:
嘿嘿
可以看到,虽然我们输入了一句话,但是我们的Java却一个字符一个字符的存入了集合c中
也就是获取字符串
import java.io.*;
public class Ex5_9io {
public static void main(String[] args) throws IOException {
BufferedReader a = new BufferedReader(new InputStreamReader(System.in));
String str;
str = a.readLine();
System.out.println(str);
}
}
运行试试
嗯,效果还可以,那就玩点花里胡哨的:
import java.io.*;
public class Ex5_9io {
public static void main(String[] args) throws IOException {
BufferedReader a = new BufferedReader(new InputStreamReader(System.in));
//获取字符串
ArrayList<String> str = new ArrayList<>();
while (true){
String st = a.readLine();
if (st.equals("quit")){
break;
}
str.add(st);
}
System.out.println(str);
}
}
我们尝试输出一堆字符串并保存在集合中。
运行结果:
这还有什么可好说的?
System.out.print\(\); 不换行输出
System.out.println\(\); 换行输出
System.out.write\(\); 输出低八位字节
System.out.printf\(\) 格式化输出(这个之前好像没说过)
System.out.println(0); //输出一个,并换行
System.out.print(1+" "); //输出一个 后面跟个空格,不换行
System.out.write('a');//输出一个字符a 不换行
System.out.println(); //加个这个,换行,美观一点
System.out.printf("这是一个数字 %d 这是一个字符串 %s ",1,"hello"); //格式化输出
运行结果:
关于对文件的操作,要说的话,有很多很多,就直接实战看例子吧
首先呢,我们先导包
import java.io.*;
可以看到,我们的文件操作的包位于java.io包中。
写入文件的相关操作位于io包中的OutputStream类中。想对文件进行操作,我们需要先利用OutputStream类的构造方法创建一个文件对象,然后根据文件对象的方法对文件进行操作。
OutputStream fwrite = new FileOutputStream("C:/java/text.txt"); //创建文件对象
for (int i = 0;i<10;i++){
//循环向里面存数据
fwrite.write(i);
}
fwrite.close(); //关闭文件
读取文件的相关操作位于io包中的InputStream类中,我们若想对文件进行操作,就和写入文件是一样的,先创建对象,再使用相关操作方法。
利用InputStream读取文件:
InputStream fread = new FileInputStream("C:/java/text.txt"); //创建文件对象
byte[] fb = fread.readAllBytes(); //创建数组接收数据
fread.close(); //关闭文件
for (byte b : fb) {
//循环读取
System.out.println(b);
}
全部代码:
import java.io.*;
public class Ex5_9io {
public static void main(String[] args) throws IOException {
OutputStream fwrite = new FileOutputStream("C:/java/text.txt");
for (int i = 0;i<10;i++){
fwrite.write( i);
}
fwrite.close();
InputStream fread = new FileInputStream("C:/java/text.txt");
byte[] fb = fread.readAllBytes();
fread.close();
for (byte b : fb) {
System.out.println(b);
}
}
}
何为多线程,通俗的讲就是让你的代码同时干好几件事。
而我们的一个代码文件或者一个项目就是一个进程,而如果我们想提高效率,我们可以多开几个文件进行多进程,也可以在进程中创建多线程(多写几个方法),但是多进程比较耗费资源,所以一般推荐多线程,在代码里,让代码做几个文件做的事。
多线程编程可以让我们的代码拥有更高效率。
犹如上图
使用多线程需要先创建一个或者多个线程
然后让线程调用CPU资源,开始运行
然后运行完毕等待所有线程运行完毕
然后删除资源,结束线程
优先级就是系统确定线程的调度顺序,但是不执行顺序,因为多线程的执行是具有无序性的。
调度顺序只是系统分配资源的顺序,不分配资源就无法执行。
如何在Java代码中创建多线程,Java内置了用于多线程的库。
我们需要写一个类A来继承Thread类,并重写run()方法。
run()方法里面放我们需要进行多线程的代码。
然后再在主类中实例化类A的对象,并且调用strat方法。
public class TheadText {
public static void main(String[] args) {
//实例化StartThread,并调用start方法使线程动起来
StartThread t1 = new StartThread("一 ");
t1.start();
StartThread t2 = new StartThread("二 ");
t2.start();
StartThread t3 = new StartThread("三 ");
t3.start();
StartThread t4 = new StartThread("四 ");
t4.start();
}
}
/**
* 1.继承Thread类并重写run方法
*/
class StartThread extends Thread{
String name;
StartThread(String name){
this.name = name;
}
@Override
public void run() {
System.out.println(name+1);
System.out.println(name+2);
System.out.println(name+3);
System.out.println(name+4);
System.out.println(name+5);
}
}
运行结果(还可以体现线程的无序性):
使用Runnable接口避免了单继承的局限性,线程类只是实现了 Runnable 接口,还可以继承其他类
public class TheadText {
public static void main(String[] args) {
StartRunnable startRunnable1 = new StartRunnable(" 一 ");
Thread te1 = new Thread(startRunnable1);
te1.start();
StartRunnable startRunnable2 = new StartRunnable(" 二 ");
Thread te2 = new Thread(startRunnable2);
te2.start();
StartRunnable startRunnable3 = new StartRunnable(" 三 ");
Thread te3 = new Thread(startRunnable3);
te3.start();
StartRunnable startRunnable4 = new StartRunnable(" 四 ");
Thread te4 = new Thread(startRunnable4);
te4.start();
}
}
/**
* 2. 实现Runnable接口,实现run方法
*/
class StartRunnable implements Runnable{
String name;
// 重载一下方法,利于区分
StartRunnable(String name){
this.name = name;
}
@Override
public void run() {
System.out.println(name+1);
System.out.println(name+2);
System.out.println(name+3);
System.out.println(name+4);
System.out.println(name+5);
}
}
运行结果:
这个我研究了挺大一会儿。
实现这个接口后,还需要实现call方法
然后通过FutureTask类来对我们实例化对象进行封装
最后还要实例化Thread类进行start操作开启我们的线程
代码演示:
public class TheadText {
public static void main(String[] args) {
//先实例化
StartCallable a = new StartCallable();
//然后调用FutureTask类
FutureTask<String> te1 = new FutureTask<>(a);
//设置我们的name属性
a.name = " 一 ";
//开启我们的线程一
new Thread(te1).start();
StartCallable b = new StartCallable();
FutureTask<String> te2 = new FutureTask<>(b);
b.name = " 二 ";
new Thread(te2).start();
StartCallable c = new StartCallable();
FutureTask<String> te3 = new FutureTask<>(c);
c.name = " 三 ";
new Thread(te3).start();
StartCallable d = new StartCallable();
FutureTask<String> te4 = new FutureTask<>(d);
d.name = " 四 ";
new Thread(te4).start();
}
}
/**
* 实现Callable接口,实现call方法
*/
class StartCallable implements Callable<String>{
String name ;
public String call() throws Exception{
System.out.println(name+1);
System.out.println(name+2);
System.out.println(name+3);
System.out.println(name+4);
return name;
}
}
运行结果:
线程在我们创建后(出生)等待CPU的资源分配,然后开始工作,在工作完我们分配的工作后,就会(死亡)消失
数据,数据库,数据库管理系统等
数据是描述事物的符号,比如音频,视频,文档,图片等可以转化为计算机可以是别的标识,转成二进制存入计算机。
从字面理解,数据库就是存储数据的仓库。具体来说就是长期存放在计算机硬件上的,有组织,可共享的数据集合。
根据数据模型的不同,数据库通常被分为层次数据库(IBM的IMS)、网状数据库(DBTG)、关系数据库(DB2、MySQL等)。
还有另一种,关系型数据库和非关系型数据库(MongoDB)。
数据库需要多个元素,共同组合成数据系统才能发挥作用。
数据库管理系统是一种操纵和管理数据库的大型软件,用于建立,使用,维护数据库。
用户通过DMBS访问数据库中的数据,数据库管理员通过DMBS维护数据库。
数据库管理系统由 用户,硬件,软件,数据库共同组成,
像我们平时所说的数据库就是数据库系统,包括数据库,软件,硬件,用户的。
而我们市面上主流的关系型数据库有:
8.0.18.0版本下载——点击链接下载 MySQL8.0.18.0
下载好之后双击安装,默认选第一个,然后一直点击next,唯一需要注意的是,设置密码的时候需要注意,不要忘掉,忘了就只能卸载重装再设置了。
然后别的就一直next就行了。
安装好之后,我们可以在开始菜单里面找到我们安装的MySQL
然后会出现这个界面
然后输入密码,就能够成功的进入我们的数据库
然后我们就可以输入命令来操作数据库了,我现在掩饰一个查看版本的命令
select version();
当前状态:status;
net start mysql80
net stop mysql80
计算机->右键->属性->高级系统配置->环境变量->在path里面把C:\Program Files\MySQL\MySQL Server 8.0\bin加进去
这个路径是按安装路径,默认都是这个路径,,但是你也可以在安装的时候更改,这里就按照默认的
配置好之后,我们就可以通过dos命令来链接MySQL了
mysql \-h localhost \-u root \-p
然后再输入密码,就可以连接到我们的数据库
当然,我们仍然可以通过开始菜单里面链接操作
一般推荐使用dos命令链接,操作
增删改查,这些都是必须会的,如果不会,那后果可是很严重!
想要操作数据库,我们需要先连接数据库
首先打开cmd
然后输入
mysql -h localhost -u root -p
显示这个就是成功了
上一篇已经说过,MySQL中由许多数据库组成,我们现在说的就是对数据库的操作
通过如下指令创建一个数据库
create database name1;
回车后会显示如下内容,表示创建成功
常见错误:
没有连接数据库直接输入语句,出现以下错误
最后的;
输入成中文,会这样
show databases; # 查看所有数据库
show create database name1; # 查看数据库 name1
回车显示:
drop database name1;
使用show databases
验证是否成功
可以看到我们的name1数据库已经没了,而看到这个text5_23没,这个就是我们用来演示下一个操作的数据库。
想要操作数据表,首先你要告诉MySQL你要操作哪个数据库中的数据表
use text5_23;
会看到:
这就代表着已经成功的进入了我们的目标数据库
创建一个数据表用来存储我们班人的姓名和学号
看这个命令前,最好先看一下MySQL的数据类型——MySQL 数据类型 | 菜鸟教程)
create table 20network(
studyid smallint not null,
studyname char(10) not null
);
not null是不能为空
敲回车会显示这样
就是已经成功的创建了一个数据表
往数据表中插入一个学号为1001,名字为 布小禅的数据
insert into 20network(
studyid,studyname)
values(
1001, "布小禅"
);
select * from 20network; # 查询表内的所有数据
select studyid from 20network; # 查询表内的学号
select studyname from 20network; # 查询姓名
结果:
delete from 20network; # 删除表内所有数据
delete from 20network where studyid=1001; # 删除学号=1001的数据
不要轻易尝试,恢复数据不容易,但是练手可以随意
show tables; # 查看当前数据库所有数据表
show create table 20network; # 查看20network表
结果:
删除需要慎用,最好不要做个删库跑路的人(手动狗头)
drop table 20network;
查一下是否删除成功
欧克成功了
jdbc是Java连接数据库的工具,需要下载jar包——MySQL8.0版本以上的jar包
在Java项目中,肯定是需要使用数据库的,因此这也是一门极其重要的课程!
首先
把我们下载的jar包导入我们的项目
1.
然后:
接着:
成功:
我们可以在idea中查看我们的数据表
也可以在idea中创建数据表,添加数据
这些只是方便我们操作数据库,那么就看看怎么用代码连接和操作把
import java.sql.*;
public class TextMySQLConnect {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//通过反射设置驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 数据库uurl前面复制刚刚连接数据库的时候的url,后面接着复制
String url = "jdbc:mysql://localhost:3306/***(这里填你MySQL里面的数据库名字)?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
// 账号
String user = "root";
// 密码
String password = "这里填写你自己的MySQL密码";
// 连接数据库
Connection coon = DriverManager.getConnection(url, user, password);
// 执行查询
Statement stmt = coon.createStatement();
// sql语句
String sql = "select * from 20network";
// 执行sql语句
ResultSet rs = stmt.executeQuery(sql);
// 查询数据表的内容,可以通过rs.get数据类型(首字母大写)("数据名");
// 比如查询学号
// 返回布尔值,成功操作返回为true
if (rs.next()){
int id = rs.getInt("studyid");
System.out.println("True");
System.out.println("学号为:"+id);
}
// 关闭
rs.close();
stmt.close();
coon.close();
System.out.println("GoodBye");
}
}
运行结果:
在Java中的sql语句不需要加**;** 并executeQuery方法无法对数据表进行操作
网络编程是编写运行在网络中不同设备中的程序。例如(QQ,微信等)。
通过网络编程,人们可以实现网络中不同设备的通讯。
软件的构成有两种方式
C/S结构是client(客户端)/server(服务器)结构,常见的有QQ,微信等桌面客户端
B/S结构是browser(浏览器)/server(服务器)结构,常见的是百度,哔哩哔哩,CSDN等各大网站
通讯协议,IP地址,端口号
网络之间的通讯需要遵循一定的网络通讯协议。
通讯协议就是让网络中的每台计算机都使用一样的规则,这样才能互相通讯。
协议就像我们平时说的语言
在中国(局域网)说汉语(中国的通讯协议就是汉语)
但是到了国际上,我说汉语,你说日语,当然无法交流
因此就需要一个统一的语言,也就是英语(协议)来规定
而提起通讯协议,就不得不说TCP/IP协议,它是网络中使用最多,最广泛的协议,当然,它并不是单单指TCP协议和IP协议,它是由:FTP、SMTP、TCP、UDP、IP等协议构成,之所以称为TCP/IP
协议是因为它们两个最具代表性。
一为UDP协议,一为TCP协议
UDP:UDP (英语:User Datagram Protocol,用户数据报协议),位于 OSI 模型的传输层。一个无连接的协议。提供了应用程序之间要发送数据的数据报。由于UDP缺乏可靠性且属于无连接协议,所以应用程序通常必须容许一些丢失、错误或重复的数据包。
TCP:TCP(英语:Transmission Control Protocol,传输控制协议) 是一种面向连接的、可靠的、基于字节流的传输层通信协议,TCP 层是位于 IP 层之上,应用层之下的中间层。TCP 保障了两个应用程序之间的可靠通信。通常用于互联网协议,被称 TCP / IP。
说白了UDP就是用于视频通话,打电话,看直播的时候,而TCP则是用在传输文件的时候。因为UDP并不安全,它在传输数据时会丢失一些数据包,而在你视频电话时,遇到这种情况时,无非就是卡了一下罢了,并不会太影响,而UDP的速率比TCP 的速率要快;不过TCP 的安全性更高,它通常在传输文件时使用,它并不会丢失数据包,但是速率上较之UDP慢。
TCP之所以会慢是因为TCP每次都需要经过三次握手,即客户端向服务端发送请求;服务端回应请求;客户端确认请求这三个过程。
IP地址是计算机的唯一标识,用于被别的计算机识别,然后连接,通讯。
就相当于我们用的身份证,代表着我们的身份。
当然因为他叫地址,我们也可以理解为我们每个人的地址,而这个理解相对于身份证号来说,对端口号的;接更为方便一些。
而IP地址分为IPv4和IPv6
IPv4有四个字节,但是却是使用十进制来表示的a.b.c.d
每个大小取值的范围是0~255,范围大致为2**32
(每个字节有8个二进制构成)也就是4294967296个,而这个值对于地球上的计算机来说,是有些不够用的,因此就出现了IPv6
IPv6有六个字节,取值范围远大于IPv4,足足有281474976710656
个,号称可以给地球上的每个沙子配上ip,IPv6的出现,解决了IPv4地址不够用的问题
我们计算机上每个软件工作时,操作系统都会给软件分配一个端口号,因为计算机只有一个IP地址,而计算机上有许许多多的软件,当我们用一个软件通讯时,虽然可以通过IP地址找到目标计算机,但是却无法找到目标计算机上对应的软件,此时就需要端口号了,这个端口号就是我们的软件能够找到目标计算机的软件的凭证。
端口号由两个字节组成,取值范围是0~65536,不过1024之前的端口我们无法使用,因为操作系统已经将其分配给了系统软件,而端口号是无法相同的。
利用地址来理解,你就会发现端口号只不过就是这样罢了:
IP地址是计算机的小区地址,而端口号是门牌号,我给你的小区送了一封信,如果没有门牌号的话,物流就无法知道这封信到底是寄给谁的。
Java网络编程是使用Java代码编写运行在网络中的多台设备的程序
Java网络编程被封装在java.net包中
而表示客户端的类是java.net.Socket
类
表示服务端的类是java.net.ServerSocket
类
而我们需要创建一个服务端和一个客户端,然后进行数据的传输
我们创建一个服务端,需要以下步骤
表示服务端的类是java.net.ServerSocket
类
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
ServerSocket server = new ServerSocket(8888); //1.创建一个服务器对象,绑定端口位8888
Socket socket = server.accept(); //2.获取链接
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
OutputStream os = lj.getOutputStream();
String name = "服务器:";
String nr = String.format("%s你好啊,客户端!", name);
os.write(nr.getBytes());
server.close();
lj.close();
服务端完整代码:
package Java进阶.netBc;
import java.io.*;
import java.net.*;
/**
* 1.创建一个服务器对象,绑定端口
* 2.获取链接
* 3.获取数据
* 4.回应数据
* 5.释放资源
*/
public class TCPServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8888); //1.创建一个服务器对象,绑定端口
Socket lj = server.accept(); //2.获取链接
InputStream is = lj.getInputStream(); //3.获取数据
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
OutputStream os = lj.getOutputStream();
String name = "服务器:";
String nr = String.format("%s你好啊,客户端!", name);
os.write(nr.getBytes());
server.close();
lj.close();
}
}
我们在客户端上需要:
而表示客户端的类是java.net.Socket
类
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
Socket socket = new Socket("127.0.0.1", 8888);
OutputStream os = socket.getOutputStream();
String nr = String.format("%s你好,服务器",name);
os.write(nr.getBytes());
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
socket.close();
全部代码
package Java进阶.netBc;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
* 1.创建Socket对象
* 2.传数据
* 3.接收响应
* 4.关闭
*/
public class TCPClint {
public static void main(String[] args) throws IOException {
String name = "客户端:";
Socket socket = new Socket("127.0.0.1", 8888);
OutputStream os = socket.getOutputStream();
String nr = String.format("%s你好,服务器",name);
os.write(nr.getBytes());
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
socket.close();
}
}
注意需要先让服务器运行起来,再运行客户端
客户端:
服务器端:
粉丝福利:
添加左侧好友领取海量Java资料
解,你就会发现端口号只不过就是这样罢了:
IP地址是计算机的小区地址,而端口号是门牌号,我给你的小区送了一封信,如果没有门牌号的话,物流就无法知道这封信到底是寄给谁的。
Java网络编程是使用Java代码编写运行在网络中的多台设备的程序
Java网络编程被封装在java.net包中
而表示客户端的类是java.net.Socket
类
表示服务端的类是java.net.ServerSocket
类
而我们需要创建一个服务端和一个客户端,然后进行数据的传输
我们创建一个服务端,需要以下步骤
表示服务端的类是java.net.ServerSocket
类
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
ServerSocket server = new ServerSocket(8888); //1.创建一个服务器对象,绑定端口位8888
Socket socket = server.accept(); //2.获取链接
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
OutputStream os = lj.getOutputStream();
String name = "服务器:";
String nr = String.format("%s你好啊,客户端!", name);
os.write(nr.getBytes());
server.close();
lj.close();
服务端完整代码:
package Java进阶.netBc;
import java.io.*;
import java.net.*;
/**
* 1.创建一个服务器对象,绑定端口
* 2.获取链接
* 3.获取数据
* 4.回应数据
* 5.释放资源
*/
public class TCPServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8888); //1.创建一个服务器对象,绑定端口
Socket lj = server.accept(); //2.获取链接
InputStream is = lj.getInputStream(); //3.获取数据
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
OutputStream os = lj.getOutputStream();
String name = "服务器:";
String nr = String.format("%s你好啊,客户端!", name);
os.write(nr.getBytes());
server.close();
lj.close();
}
}
我们在客户端上需要:
而表示客户端的类是java.net.Socket
类
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
Socket socket = new Socket("127.0.0.1", 8888);
OutputStream os = socket.getOutputStream();
String nr = String.format("%s你好,服务器",name);
os.write(nr.getBytes());
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
socket.close();
全部代码
package Java进阶.netBc;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/**
* 1.创建Socket对象
* 2.传数据
* 3.接收响应
* 4.关闭
*/
public class TCPClint {
public static void main(String[] args) throws IOException {
String name = "客户端:";
Socket socket = new Socket("127.0.0.1", 8888);
OutputStream os = socket.getOutputStream();
String nr = String.format("%s你好,服务器",name);
os.write(nr.getBytes());
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
socket.close();
}
}
注意需要先让服务器运行起来,再运行客户端
客户端:
服务器端: