!!!本文适合有c和c++基础的,通过比较c++和java的不同,快速入门java。!!!
这篇文章主要是介绍和c++不同的地方,没说的知识点按照c++写就行了。
Java是面向对象的程序。首先对于Java来说一个文件就是一个类,而且类名必须和文件名一致,比如Main类,则文件名要叫做Main.java,而Person类,文件名要叫做Person.java。
它和c++首先映入眼帘的不同就是不可以在类外定义函数,它所有的函数(包括主函数都要定义在类里面)。
比如在一般只有一个文件的话c++结构是这样的:
#include
using namespace std;
int main(){
//代码
return 0;
}
但是Java的话main函数也要放在类里面:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
//代码
}
}
注:public static void main(String[] args) {}是主函数(或者叫程序入口)的唯一格式,不能写成其他形式。类的话命名随意。
【1】在类外定义方法
c++中允许在类外定义方法,比如
#include
using namespace std;
void print(){
cout<<"666";
}
int main(){
print();
return 0;
}
在Java中应该这么写:
import java.util.Scanner;
public class Main {
public static void speak(){
//下面这句话是Java的控制台输出语句,相当于printf或者cout
System.out.println("666");
}
public static void main(String[] args) {
speak();
}
}
注意因为main函数为静态方法,学过c++都知道,静态方法属于类中的所有实例所共有,并且只能调用静态的变量和方法,所以speak函数必须是static才能被main函数调用,至于是要public还是private看你自己。
【2】在类内定义方法
当然c++也可以在类内定义方法:
#include
using namespace std;
class Person{
public:
void speak(){
cout<<"666";
}
};
int main(){
Person person;
person.speak();
return 0;
}
改写成Java是这样的:
import java.util.Scanner;
public class Main {
static class Person{
public void speak(){
System.out.println("666");
}
};
public static void main(String[] args) {
Person person=new Person();
person.speak();
}
}
因为Java中一个文件只能是一个类,所以Person类只能作为内部类存在于Main中,所以Person前面也要加上static关键字才能被同为静态方法的main函数调用。
当然Java也可以像c++那样分文件编写(因为下面是定义在同一个包内,所以不用引包)
我们可以重新创建一个文件Person.java来定义Person类。
public class Person{
public void speak(){
System.out.println("666");
}
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Person person=new Person();
person.speak();
}
}
【1】包是什么
c++中没有包的概念。那么包是什么呢?
当程序足够大的时候,我们就要学会去管理我们代码。写程序的时候代码管理很重要。在c++中,比如当零散的代码足够多时,我们就要用函数去分类包装这些代码,将一部分代码抽象成这个函数,另一部分代码抽象成另一个函数。当函数足够多时,我们要将方法分类,进一步抽象,一部分函数属于这个类,一部分函数当成那个类的方法,用类包装。
但是当类足够多,我们就要进一步分类,一部分类放在这个命名空间,一部分类放在那个命名空间。
包说白了就是文件夹,作用就类似于命名空间,用来对各个类进行分类管理,一部分包放在这个文件夹,另一部分包放在那个文件夹。
【2】案例:新建一个Util包,将Person类放在Util中
package util;
public class Person{
public void speak(){
System.out.println("666");
}
}
import util.Person;
public class Main {
public static void main(String[] args) {
Person person=new Person();
person.speak();
}
}
【3】包名命名规则
上面只是个示例:比较正式的项目要采用以下的命名规则
公司域名反写+包的名字(要体现作用),需要全部英文小写,见名知意
例:com.flyingpig.entity com.flyingpig.util【其中com.flyingpig是域名】
简单说就是建立一个com文件夹,里面再建立一个flyingpig文件夹,然后里面就可以建立entity文件夹来存放实体类,建立util文件夹来存放工具类
在com.flyingpig.entity包下的Student类表示为com.flyingpig.entity.Student ,这个叫做全类名和全限定名。
【3】我们看到Person类上面加了个package,而Main类上面import。
这是因为类放在包里要package。
而引用放在别的包里的类需要引包。具体的引包规则如下:
(1)使用同一个包中的类时,不需要导包
(2)使用于java.lang包中的类时,不需要导包
(3)其他情况都需要导包
(3)如果同时使用两个包中的同名类,需要用同类名.
单行注释://
多行注释:/* */
文档注释:/** **/
字面量--整型,小数,字符串,字符,布尔类型,空类型(null)
变量类型--四类八种
和c++基本一致,不一样的是多了像byte之类类型,少了像long double之类的类型。
输出:System.out.println方法
//输出字符串字面量
System.out.println("我可以输出任何变量哦");
//输出整型字面量
System.out.println(666);
//输出整型变量
int a=0;
System.out.println(a);
//注意long类型的数据值后面一般需要加个L或l作为后缀。
long n=9999999999L;
System.out.println(n);
//注意float类型的数据值后面一般需要加个F作为后缀。
float f=10.1F;
System.out.println(f);
输入:用Scanner类
//建立一个调用Scanner的有参构造建立一个Scanner对象
Scanner scanner=new Scanner(System.in);
///调用其中的方法进行输入,其中nextInt方法是用来输入整数的
int number=sc.nextInt();
和c++几乎一样,只有些许不同,这里列举几个不同点。
(1)%也能用于小数运算
(2)bool类型不能用于算数计算
(3)java中对的数据类型转换检查严格
下面的代码在c++中是可以的,但在java中就会报错。
int a=1.1;
写法与c++一模一样。
基本数据类型 【上面讲的四类八种】
数据值是存储在自己的空间中。
特点:赋值给其他变量,也是赋的是真实的值。
引用数据类型--就是java中表示对象的数据类型。
数据值是存储在其他空间中,自己空间中存储的是地址值。类似于c++的引用。它们一样都是赋值之后就不能修改指向的对象,使用上都相当于别名。
特点:赋值给其他变量,赋的地址值。
因为java和c++不同的是,java创建对象都是在堆区new出来的,所以都使用引用数据类型来操作对象。
例如:
在c++中可以
Person person;
但是java中必须用new来创建对象:
Person person=new Person();
这里的Person与c++的Person不一样,它代表引用,就像下面c++的Person*,不同的是上面是引用而下面是指针。
Person* person=new Person();
Java中的引用相比于c++更加方便安全,因为它不用手动释放空间。
Java中的链表就是通过引用数据类型实现的。
在java中,数组是一种对象。
创建数组
public static void main(String[] args) {
//int数组的类型名叫做int[],所以一般是这样写的
int[] array1=new int[3];
//但是如c++之类的语言一般习惯用int array2[]这种格式,所以也可以这么写
int array2[]=new int[3];
//当然了,赋值的话还可以用数组专门用于赋值的初始化列表
int[] array3=new int[]{11,22,33};
//也可以简化写成
int[] array4={11,22};
}
使用的话和c几乎一样,但还是有不同。
(1)因为是变量,所以java里面的数组有属性size可以来获取数组的长度,如
array3.length。这个比较经常在循环中用到。
(2)还有数组越界,在java中不会纵容数组越界,一越界会抛出异常。
和c,c++差不多,就像第零条所讲的,最大的不同就是所有方法,包括main方法都得在类里面定义。
在c++中是访问权限: 属性/行为:
class Person{
public:
void speak(){
cout<<"666";
}
};
在Java中是访问权限 属性/行为:
class Person{
public void speak(){
cout<<"666";
}
};
为什么要刻意强调这一点呢?因为与c++不同的是java方法中建立变量没有初始化会报错。但是类中对象没有初始化会像c++一样分配初始值。
整型的初始值是0。浮点型是0.0。布尔型是false。引用类型是null。
前面讲过java是通过new来创建对象的。
//无参构造
Student student1=new Student();
//有参构造
Student student2=new Student("张三",19);
补充:
Java中没有析构函数。
set和get方法可以通过IDEA的快捷键alt+insert进行快速生成。当然后期会使用lombok来简化书写。
c++中是这么写的this->
java中是这么写的this.
c++是这么调用的Person::m_A
Java是这么调用的Person.m_A
【1】Java中专门用来描述一类事物的类就叫做Javabean类,简单说就是里面没有main方法。
【2】里面有main方法的类叫做测试类,因为有main方法,所以可以运行,主要用来测试本类和其他类的方法书写是否正确。
【3】专门提供方法让别人使用的就是工具类。最大的特点就是变量和方法都是静态的。
例如下面这个代码
public class JwtUtil {
//有效期为
public static final Long JWT_TTL =15*24* 60 * 60 *1000L;// 60 * 60 *1000 一个小时
//设置秘钥明文
public static final String JWT_KEY = "Zmx5aW5ncGln";//flyingpig
public static String getUUID(){
String token = UUID.randomUUID().toString().replaceAll("-", "");
return token;
}
/**
* 生成jtw
* @param subject token中要存放的数据(json格式)
* @return
*/
public static String createJWT(String subject) {
JwtBuilder builder = getJwtBuilder(subject, null, getUUID());// 设置过期时间
return builder.compact();
}
/**
* 生成jtw
* @param subject token中要存放的数据(json格式)
* @param ttlMillis token超时时间
* @return
*/
public static String createJWT(String subject, Long ttlMillis) {
JwtBuilder builder = getJwtBuilder(subject, ttlMillis, getUUID());// 设置过期时间
return builder.compact();
}
private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
SecretKey secretKey = generalKey();
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
if(ttlMillis==null){
ttlMillis=JwtUtil.JWT_TTL;
}
long expMillis = nowMillis + ttlMillis;
Date expDate = new Date(expMillis);
return Jwts.builder()
.setId(uuid) //唯一的ID
.setSubject(subject) // 主题 可以是JSON数据
.setIssuer("flyingpig") // 签发者
.setIssuedAt(now) // 签发时间
.signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥
.setExpiration(expDate);
}
/**
* 创建token
* @param id
* @param subject
* @param ttlMillis
* @return
*/
public static String createJWT(String id, String subject, Long ttlMillis) {
JwtBuilder builder = getJwtBuilder(subject, ttlMillis, id);// 设置过期时间
return builder.compact();
}
public static void main(String[] args) throws Exception {
String jwtKey = "flyingpig";
String encodedKey = Base64.getEncoder().encodeToString(jwtKey.getBytes());
System.out.println(encodedKey);
}
/**
* 生成加密后的秘钥 secretKey
* @return
*/
public static SecretKey generalKey() {
byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
//解析JWT令牌
public static Claims parseJwt(String jwt) {
SecretKey secretKey = generalKey();
return Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt)
.getBody();
}
}
然后我们就可以直接通过类名.方法的格式直接对里面的方法为其他类提供服务。
Java 中的增强 for 循环(也称为 for-each 循环)相比于传统的 for 循环
优点:
1. 简洁,不需要索引
2. 安全性:防止越界(没有使用索引)和修改集合中的元素。
缺点:
1. 无法获取当前元素的索引:增强 for 循环没有提供内置的索引访问机制,如果需要获取当前元素的索引,仍然需要使用传统 for 循环。
2. 无法修改集合中的元素:增强 for 循环只能读取集合中的元素,无法修改元素的值或删除元素。
需要注意的是,增强for并不会提高程序的运行效率。在底层实现上,增强 for 循环其实还是通过迭代器或索引来遍历集合或数组的。
for (元素类型 元素变量 : 遍历对象) {
// 循环体
}
其中,元素类型表示遍历对象中元素的类型,元素变量是用于接收每个元素值的变量名,遍历对象可以是数组或实现了 Iterable 接口的集合类(如 List、Set 等)。
下面是几个示例:
1. 遍历数组:
int[] numbers = {1, 2, 3, 4, 5};
for (int number : numbers) {
System.out.println(number);
}
2. 遍历集合:
List fruits = Arrays.asList("apple", "banana", "orange");
for (String fruit : fruits) {
System.out.println(fruit);
}
3. 遍历字符串:
String message = "Hello";
for (char ch : message.toCharArray()) {
System.out.println(ch);
}
在以上示例中,每次迭代时,元素变量(如 number、fruit、ch)都会被赋值为遍历对象中的一个元素值,然后执行循环体内的代码。循环将按顺序遍历遍历对象中的每个元素,直到遍历完成。