java语言简单介绍:
Java是一门面向对象编程语言,它吸收了C++语言中抽象化对象与封装继承等优点,摒弃了C++里较为难理解的多继承、指针等概念,因此Java语言不仅功能强大而且简单易用。
Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。
个人来说,java语言相较于C++,确实是比较容易上手,并且在现在这个市场需求下,java的生存环境还是比较好的,各种求职网站给出的薪酬也比较高,是最卷(狗头)但也是最容易找到工作的一种语言。
① 不可使用java关键字和保留字,但是可以包含关键字和保留字.
② 可以使用26个字母大小写,数字0-9,$和_.
③ 可以使用数字,但不可放在首位.
④ 长度理论上没有限制,但命名最好能反映出其作用,遵循”驼峰形式”,见名知意
⑤ 包名全部小写,类名全部大驼峰式
⑥ 变量名、方法名首字母小写,如果名称由多个单词组成,每个单词的首字母都要大写
⑦ 常量(特指被 final 修饰的常量)名全部大写,如果是单个字母,需要大写,如果是多个单词,需要用下划线分开。并且都大写
总的来说,java中变量的命名规则与其他语言感觉也没有特别大的差异。
变量有两个相关概念,一个是变量的名字,一个是变量的值,即变量在内存中所占的小区域是有名字的,这个小区域里面还装着一个值,根据小区域的名字来访问这个小区域里面的值。不同的变量类型在内存中分配不同大小的存储空间,每一个变量都有自己特定的数据类型,当给变量声明了不同的数据类型它就在内存中占用不同的存储空间。
这些基本学一下操作系统与计算机组成原理的同学都会有一些概念。
字符常量:凡是用单引号引起来的单个字符,就做字符常量。例如:、‘b’、’9’、‘中‘
字符串常量:凡是用双引号引起来的部分,叫做字符串常量。例如:“abc”、“Hello”、“123”
整数常量:直接写上的数字,没有小数点。例如:100、200、0、-250
浮点数常量:直接写上的数字,有小数点。例如:2.5、-3.14、0.0
布尔常量:只有两种取值 true | false
java中8种基础类型:
byte 数据类型是8位、有符号的,以二进制补码表示的整数,默认值为0
表达范围是:-128(-2^7) ~ 127(2^7-1)
取值范围已经定义在包中:Byte.SIZE,Byte.MIN_VALUE,Byte.MAX_VALUE
short 数据类型是16位、有符号的以二进制补码表示的整数,默认值为0
表达范围:-32768(-2^15) ~ 32767(2^15 - 1)
取值范围已经定义在包中:Short.SIZE,Short.MIN_VALUE,Short.MAX_VALUE
int数据类型是32位、有符号的以二进制补码表示的整数,默认值为0
表达范围:-2,147,483,648(-2^31) ~ 2,147,483,647(2^31 - 1)
取值范围已经定义在包中:Integer.SIZE,Integer.MIN_VALUE,Integer.MAX_VALUE
long数据类型是64位、有符号的以二进制补码表示的整数,默认为0L
表达范围:(-2^63) ~ (2^63 -1)
取值范围已经定义在包中:Long.SIZE,Long.MIN_VALUE,Long.MAX_VALUE
float 数据类型是单精度、32位、符合IEEE 754标准的浮点数,默认值为0.0f
取值范围已经定义在包中:Float.SIZE,Float.MIN_VALUE,Float.MAX_VALUE
double数据类型是双精度、64位、符合IEEE 754标准的浮点数,默认值为0.0d
取值范围已经定义在包中:Double.SIZE,Double.MIN_VALUE,Double.MAX_VALUE
boolean数据类型表示一位的信息,只有两个取值:true和false,默认值为false
char类型是一个单一的16位Unicode字符
取值范围已经定义在包中:Character.SIZE,Character.MIN_VALUE,Character.MAX_VALUE
总的来说,除byte类型Java独有,布尔类型名称不同,char类型为16位的unicode,其他基本与C++差别不大。
C语言编译好的程序为什么不能够移植,比如把 .exe文件放到Linux下就执行不了了,其中有一个很大的原因就是C语言定义的变量在不同的操作系统下所占的字节大小是不一样的。声明一个int 类型的变量,它在Windows下占32位,而放到Linux下就有可能只占16位,那所表示的数值大小就不一样了,在Windwos下声明一个很大的数它在Linux下就可能会溢出。这也是C语言编译之后不能够移植的一个原因。
Java的数组与C++中的数组有明显的区别
int[] arrs1 = new int[5];
int[] arrs2 = {
1,2,3,4,5};
int[] arrs3 = new int[]{
1,2,3,4,5};
在C++中字符串为string(注意此处的s为小写),而在Java中为String
首先说明的是String与char是完全不同的类型,sizeof(string)时,恒为24,而char时为1
但是,可以通过强行数据转换的方法实现char对String的查看。
string a="123asdasdasd" /*+'\0'*/;
char *c =(char*)&a;
while (c++&&*c) {
cout<<*c;
}
cout<<endl;
输出:
123asdasdasd
由此可见String的存储类型是类似于char[]类型的,他的结尾也为‘\0’。
字符串拼接有concat方法
a = a.concat(“1231231”);
在Java中,字符串有着equals方法进行比较
String a = "hahhaha";
String b = "123";
if(a.equals(b)){
System.out.println("Equal!!");
}
else{
System.out.println("Is not equal!!");
}
基本与c++差不多,有一个instanceOf 运算符,是C++所没有的。
该运算符用于操作对象实例,检查该对象是否是一个特定类型(类类型或接口类型)
使用实例:
例1:
String name = 'James';
boolean result = name instanceOf String; // 由于name是Strine类型,所以返回真
例2:
class Vehicle {
}
public class Car extends Vehicle
{
public static void main(String args[])
{
Vehicle a = new Car();
boolean result = a instanceof Car;
System.out.println( result);
}
}
JAVA有个Math类,包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数。
Math 的方法都被定义为 static 形式,通过 Math 类可以在主函数中直接调用
C++的控制语句,Java中基本完全兼容
Java中也有着类似Python/Swift的for循环遍历方法
(不过现在C++11也有auto了,差不多)
int[] arrs = {
1,2,3,5};
for (int i : arrs)
System.out.println(i);
//注意此处为输出i而非arrs[i]
在程序中,尤其是复杂的程序中,适当地加入注释可以增加程序的可读性,有利于程序的修改、调试和交流。注释的内容在程序编译的时候会被忽视,不会产生目标代码,也就是,注释的部分不会对程序的执行结果产生任何影响。
1.) 单行注释格式。所有从“//”开始到行末的字符都将被忽略
// single line
2.) 段落注释格式。所有在“/* ”和 “*/ ”之间的字符被忽略,这些注释可以扩展到多行。
/* any section */
3.) 文档注释格式。所有在“/** ”和 “ */”之间的字符被忽略,这些注释只能应用在声明语句之前,因为它们将被Java文档生成器用于自动创立文档。
/** any section ,used by javadoc to generate HTML documents */
面向对象是java最重要的特点,它将跟对象有关的功能都封装在其内,做到“万物皆对象”
虽然很多人根我一样没有对象,但学习java的过程必须要面对对象,所以这也是新手学习道路上的第一道坎。
相信我,只要学好java,什么东西在你眼里,它都是对象!!!
类表示一个共性的产物,是一个综合的特征,而对象,是一个个性的产物,是一个个体的特征。 (类似生活中的图纸与实物的概念。)
类必须通过对象才可以使用,对象的所有操作都在类中定义。
对象的定义格式如下: 类名称 对象名称 = new 类名称() ;
如果要想访问类中的属性或方法(方法的定义),则可以依靠以下的语法形式:
访问类中的属性: 对象.属性 ;
调用类中的方法: 对象.方法(实际参数列表) ;
注意点:
public static void main(String[] args){
//Math2 m=new Math2();
//int num=m.sum(100,200);
//不通过创建对象名,直接实例对象调用,这就是匿名对象。因为没有对象名指向对象,所以只能调用一次,然后被GC回收。
int num = new Math().sum(100,200);
System.out.println(num);
}
class Math2{
int sum(int x,int y){
return x+y;
}
}
在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。
广泛意义上的内部类一般来说包括这四种:
成员内部类
局部内部类
匿名内部类
静态内部类
成员内部类是最普通的内部类,它的定义为位于另一个类的内部,形如下面的形式
public class Demo{
public static void main(String[] args){
//外部使用成员内部类
Outer outter = new Outer(100);
Outer.Inner inner = outter.new Inner();
inner.say(); //输出:200
// 100
}
}
class Outer {
private double x = 0;
public Outer(double x) {
this.x = x;
}
class Inner {
private double x=200;
//内部类
public void say() {
System.out.println(x);
System.out.println(Outer.this.x);
}
}
}
特点: 成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。 不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。
如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类.this.成员方法
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
例如:
interface Person{
public void say();
}
public class Demo{
public static void main(String[] args){
//局部内部类
class PersonImp implements Person{
@Override
public void say(){
System.out.prinln("新编写的局部内部类的say方法内容");
}
}
PersonImp p=new PersonImp();
//这里想调用haha()方法,但是需要一个Person类,为此专门创建一个class文件类很浪费时间,所以使用局部内部类
haha(p);
}
public static void haha(Person p){
}
}
//窗口关闭
public static void main(String[] args){
Frame f=new Frame("QQ登陆器");
f.setVisible(true);
f.setSize(300,200);
class MyWindowListener implements WindowListener{
@Override
public void windowClosing(WindowEvent e){
System.out.println("哈哈哈");
}
}
MyWindowListener l=new MyWindowListener();
//想要添加一个窗口关闭的事件,可以使用局部类
f.addWindowListener(l);
}
注意:局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。局部内部类也是只能访问final类型变量。
匿名内部类由于没有名字,所以它的创建方式有点儿奇怪。匿名内部类创建出来只能使用一次,和匿名对象类似。创建格式如下:
new 父类构造器(参数列表)|实现接口() {
//匿名内部类的类体部分
}
interface Person{
public void say();
}
public class Demo{
public static void main(String[] args){
//匿名内部类
Person p=new Person(){
public void say(){
System.out.println("锄禾日当午");
}
}
haha(p);
}
public static void haha(Person p){
}
}
在这里我们看到使用匿名内部类我们必须要继承一个父类或者实现一个接口,当然也仅能只继承一个父类或者实现一个接口。同时它也是没有class关键字,这是因为匿名内部类是直接使用new来生成一个对象的引用。当然这个引用是隐式的。
在使用匿名内部类的过程中,我们需要注意如下几点:
1、使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
2、匿名内部类中是不能定义构造函数的。
3、匿名内部类中不能存在任何的静态成员变量和静态方法。
4、匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
5、匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
6、只能访问final型的局部变量。JDK1.8之后变量默认为final类型,但是只要第二次赋值,就不再是final类型的了。
只能访问final类型的局部变量的原因,因为局部类编译的时候是单独编译成一个文件,所以在文件中有final变量的备份。
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。
静态内部类是不需要依赖于外部类对象的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法。
格式:
public class Demo {
public static void main(String[] args) {
Book.Info info = new Book.Info();
info.say();
}
}
class Book {
static class Info {
public void say(){
System.out.println("这是一本书");
}
}
}
在Java中有一个设计的原则“一切皆对象”,那么这样一来Java中的一些基本的数据类型,就完全不符合于这种设计思想,因为Java中的八种基本数据类型并不是引用数据类型,所以Java中为了解决这样的问题,引入了八种基本数据类型的包装类
但是,以上的八种包装类也是分为两种大的类型的:
以下以Integer和Float为例进行操作
将一个基本数据类型变为包装类,那么这样的操作称为装箱操作。
将一个包装类变为一个基本数据类型,这样的操作称为拆箱操作,
因为所有的数值型的包装类都是Number的子类,Number的类中定义了如下的操作方法。
拆箱操作:
装箱操作:
在JDK1.4之前 ,如果要想装箱,直接使用各个包装类的构造方法即可,例如:
int temp = 10 ; // 基本数据类型
Integer x = new Integer(temp) ; // 将基本数据类型变为包装类
在JDK1.5,Java新增了自动装箱和自动拆箱,而且可以直接通过包装类进行四则运算和自增自建操作。例如:
Float f = 10.3f ; // 自动装箱
float x = f ; // 自动拆箱
System.out.println(f * f) ; // 直接利用包装类完成
System.out.println(x * x) ; // 直接利用包装类完成
使用包装类还有一个很优秀的地方在于:可以将一个字符串变为指定的基本数据类型,此点一般在接收输入数据上使用较多。
在Integer类中提供了以下的操作方法:
public static int parseInt(String s);//将String变为int型数据
在Float类中提供了以下的操作方法:
public static float parseFloat(String s);//将String变为Float
在Boolean 类中提供了以下操作方法:
public static boolean parseBoolean(String s);//将String变为boolean
等等操作还有很多
1、包装类是对象,拥有方法和字段,对象的调用都是通过引用对象的地址,基本类型不是
2、包装类型是引用的传递,基本类型是值的传递
3、声明方式不同,基本数据类型不需要new关键字,而包装类型需要new在堆内存中进行new来分配内存空间
4、存储位置不同,基本数据类型直接将值保存在值栈中,而包装类型是把对象放在堆中,然后通过对象的引用来调用他们
5、初始值不同,eg: int的初始值为 0 、 boolean的初始值为false 而包装类型的初始值为null
6、使用方式不同,基本数据类型直接赋值使用就好 ,而包装类型是在集合如 coolection Map时会使用
抽象类使用abstract class 进行声明
一个抽象类中可以没有抽象方法
而抽象方法必须写在抽象类或者接口中
abstract class 类名{
// 抽象类
}
只进行声明而不进行具体实现的方法(即没有{})
抽象方法要加abstract关键字
// 抽象类
abstract class 类名{
public abstract void 方法名() ; // 抽象方法,只声明而未实现
}
如果一个类中的全部方法都是抽象方法,全部属性都是全局常量,那么此时就可以将这个类定义成一个接口。
定义格式:
interface 接口名称{
全局常量 ;
抽象方法 ;
}
使用接口的优点:
降低程序的耦合性
易于程序的扩展
有利于程序的维护
因为接口本身都是由全局常量和抽象方法组成 , 所以接口中的成员定义可以简写:
1、全局常量编写时, 可以省略public static final 关键字,例如:
public static final String INFO = "内容" ;
//简写后:
String INFO = "内容" ;
2、抽象方法编写时, 可以省略 public abstract 关键字, 例如:
public abstract void print() ;
//简写后:
void print() ;
使用关键字implements
接口可以多实现,如果一个接口要想使用,必须依靠子类。
子类(如果不是抽象类的话)要实现接口中的所有抽象方法。
class 子类 implements 父接口1,父接口2...{
}
/*以上的代码称为接口的实现。那么如果一个类即要实现接口,
又要继承抽象类的话,则按照以下的格式编写即可: */
class 子类 extends 父类 implements 父接口1,父接口2...{
}
使用关键字extends
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实力域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
继承的限制:Java中只有单继承,多重继承,没有多继承(即一个子类只能有一个父类)。多重继承通俗来讲就是爷爷、爸爸、孙子。
接口因为都是抽象部分, 不存在具体的实现, 所以允许多继承,例如:
interface C extends A,B{
}
student类实例化时先实例化person,默认调用的person的无参构造方法
public class Demo{
public static void main(String[] args){
Student student = new Student();
student.say();
}
}
class Person{
private String name;
private int age;
public Person(){
supper();//平时supper()可以省略,作用时默认调用父类的无参构造方法
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public void say(){
System.out.println("姓名:"+name+",年龄:"+age);
}
}
class Student extends Person{
Student(){
supper("张三",1);
}
}
//结果为:
//姓名:张三,年龄:1
supper关键字可以访问父类的构造方法、属性、方法。
通过supper调用父类构造方法的代码,必须写在第一行。
supper和this调用构造函数时都需要放在第一行,但是两者不会同时使用,因为不可能调用自身构造函数的同时还调用父类的构造方法
1、抽象类要被子类继承,接口要被类实现。
2、接口只能声明抽象方法,抽象类中可以声明抽象方法,也可以写非抽象方法。
3、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
4、抽象类使用继承来使用, 无法多继承。 接口使用实现来使用, 可以多实现
5、抽象类中可以包含static方法 ,但是接口中不允许(静态方法不能被子类重写,因此接口中不能声明静态方法)
6、接口不能有构造方法,但是抽象类可以有
7、1.8后接口允许出现有方法体的方法
多态就是对象的多种表现形式
对象的多态性:
从概念上非常好理解,在类中有子类和父类之分,子类就是父类的一种形态 ,对象多态性就从此而来
方法的多态:
方法的重载 和 重写 也是多态的一种, 不过是方法的多态(相同方法名的多种形态)。
多态的使用:对象的类型转换:
类似于基本数据类型的转换:
public class Demo{
public static void main(String[] args){
Student student1=new Student();
Nurse nurse1=new Nurse();
//向上转型,父类引用指向子类对象
Person person1=student1;
person1.say(); //输出:我是学生
Person person2=nurse1;
person2.say(); //输出:我是护士
//向下转型
Student student2=(Student)person1;
student2.say(); //输出:我是学生
//向下转型需要注意的是不能把原来是护士的张三转成学生 例如:
Student student3=(Student)person2;
student3.say(); //此处会报错
//向上转型比较高级的用法
Student student4=new Student();
say(student4); //输出:我是学生
}
public static void say(Person person){
person.say();
}
}
abstract class Person{
public abstract void say();
}
class Student extends Person{
@Override
public void say(){
System.out.println("我是学生");
}
}
class Nurse extends Person{
@Override
public void say(){
System.out.println("我是护士")
}
}
向上转型的对象,是通过父类调用子类覆盖或继承父类的方法,不是父类的方法。而且此时父类对象不能调用子类特有的方法。
这里又提到之前说的呢个关键字Instanceof,它可以判断某个对象是否是指定类的实例,返回boolean类型的数据
Object类是所有类的父类(基类),如果一个类没有明确的继承某一个具体的类,则将默认继承Object类。
使用Object可以接收任意的引用数据类型
public static void main(String[] args){
String text="123";
say(text);
int a=10;
say(a);
}
public static void say(Object o){
System.out.println(o)
}
建议重写Object中的toString方法。 此方法的作用:返回对象的字符串表示形式 ;
Object的toString方法, 返回对象的内存地址 ;
System.out.println(对象名)一般输出时调用的时对象的toString方法 ;
建议重写Object中的equals(Object obj)方法,此方法的作用:指示某个其他对象是否“等于”此对象。
***Object的 equals方法:***实现了对象上最具区别的可能等价关系; 也就是说,对于任何非空引用值x和y ,当且仅当 x和y引用同一对象
( x == y具有值true )时,此方法返回true 。
equals方法重写时的五个特性:
自反性 :对于任何非空的参考值x , x.equals(x)应该返回true 。
对称性 :对于任何非空引用值x和y , x.equals(y)应该返回true当且仅当y.equals(x)回报true 。
传递性 :对于任何非空引用值x , y和z ,如果x.equals(y)回报true个y.equals(z)回报true ,然后 x.equals(z)应该返回true 。
一致性 :对于任何非空引用值x和y ,多次调用x.equals(y)始终返回true或始终返回false ,前提是未修改对象上的equals比较中使用的信息。
非空性 :对于任何非空的参考值x , x.equals(null)应该返回false 。
class Person{
private String name;
private int age;
public boolean equals(Object o){
//判断内存地址是否相同
if(this==o){
return true;
}
//非空性
if(o==null){
return false;
}
//判断是否是同一个类
if(o instanceof Person){
//向下转型
Person p2=(Person)o;
//此处调用的是String里的equals()方法,和Object不同
if(this.name.equals(p2.name)&&this.age==p2.age){
return true;
}
}
return false;
}
}
equals和==的区别
前者是比较两个数是否等价,后者是比较地址
一个方法中定义完了参数,则在调用的时候必须传入与其一一对应的参数,但是在JDK 1.5之后提供了新的功能,可以根据需要自动传入任意个数的参数。
返回值类型 方法名称(数据类型…参数名称){
//参数在方法内部 , 以数组的形式来接收
}
public class Demo{
public static void main(String[] args){
System.out.println(sum(1)); //输出:1
System.out.println(sum(1,2)); //输出:3
System.out.println(sum(1,2,3)); //输出:6
System.out.println(sum(1,2,3,4)); //输出:10
}
public static int sum(int... nums){
int n=0;
for(int i=0;i<nums.length;i++){
n+=num[i];
}
return n;
}
}
2021/4/28 21:00
之后会继续更新。。。。。。