JavaEE(1)

目录

1、Java初步 

计算机语言的发展历史

Java简史

 Java体系结构

Java特点 

Java核心机制

跨平台原理(虚拟机)

​编辑

垃圾收集机制

常用DOS命令

 Java环境准备

 JDK、JRE、JVM三者间的关系  

安装notepad++

第一个Helloword 

​编辑

2、数据类型

标识符

关键词

​编辑

扩展:字符集和字符编码

变量和常量

字面常量

基本数据类型

 整数类型

 浮点类型

字符类型

 布尔类型

基本数据类型转换 

3、运算符

算法运算符

【3】

​编辑

 赋值运算符

关系运算符

逻辑运算符

三目运算符

位运算符

 运算符的级别

4、控制流程

分支

if

 switch

循环:while、do while、for

break

​编辑

continue、return

双重循环

乘法口诀

打印各种形状

三重循环

5、方法

方法的定义、调用

方法的重载

递归

求阶乘,斐波那契数列 

6、数组

引入

数组的学习

数组声明创建三种方式

数组的应用

数组的最值问题

查询

添加元素

删除元素

main方法讲解

​编辑

可变参数 

Arrays工具类

 二维数组

​编辑

​编辑

 基于数组的算法讲解

 排序

冒泡排序

选择排序

查找

顺序查找

7、面向对象

 类和对象

构造器

局部变量和成员变量

内存分析

 this

static

 三大特性

 继承

​编辑

继承内存

 权限修饰符

重写和重载

 super

 toString

equals 

类之间的关系

多态

内存分析

 简单工厂设计模式

final

 抽象类、抽象方法

接口

实现比较

内部类

垃圾回收机制


1、Java初步 

计算机语言的发展历史

      

加法:1101-------  助记符 add ....load
计算机上----操作系统----屏蔽了人和计算机接触的障碍

c++:面向对象不彻底
真正意义上的第一个彻底的面向对象的语言:java
c# ------>基于java  语法很像  

Java简史

1.SUN公司是一家什么样的公司?
美国SUN(Stanford University Network)公司
在中国大陆的正式中文名为“太阳计算机系统(中国)有限公司”
在台湾中文名为“升 阳电脑公司”。
2.Java为什么被发明?
                                Green项目。
                                应用环境:像电视盒这样的消费类电子产品
                                要求:
                                语言本身是中立的,也就是跨平台
                                        1996年Java第一次发布就引起了人们的极大兴趣。关注Java的人士不仅限于计算机出版界,  还有诸如《纽约时报》《华盛顿邮报》《商业周刊》这样的主流媒体。Java 是第一种也是唯一种在National Public Radio上占用了10分钟时间来进行介绍的程序设计语言,并且还得到了$100000000的风险投资基金。这些基金全部用来支持用这种特别的计算机语言开发的产品。重温那些令人兴奋的日子是很有意思的。我们将简要地介绍一下Java语言的发展历史:
        Java的历史要追溯到1991年,由Patrick Naughton 及其伙伴James Gosling (一个全能的计算机奇才)带领的Sun公同的工程师小组想要设计一种小型的计算机语言,主要用于像有线电视转换盒这类的消费设备。由于这些消费设备的处理能力和内存都很有限,所以语言必须非常小且能够生成非常紧凑的代码。另外,由于不同的厂商会选择不同的中央处理器(CPU),因此这种语言的关键是不能与任何特定的体系结构捆绑在一起。这个项目被命名为"Green"。
        所有就要求有这样的一种代码: 代码短小、紧凑且与平台无关。
        但是,Sun公司的人都有UNIX的应用背景。因此,所开发的语言以C++为基础。
                     是Gosling率先创造了这个语言,把这种语言称为“Oak"(这么起名的原因大概是因为他非常喜欢自己办公室外的橡树)。Sun 公司的人后来发现Oak是一种已有的计算机语言的名字,于是,将其改名为Java。


         
3.Java的发明人?
James  Gosling
 
                 
        
4.java历史详述:
 
1991年:Green项目,Oak语言 

1995年5月23日,Java语言诞生;

1996年1月,第一个JDK-JDK1.0诞生;

1996年4月,10个最主要的操作系统供应商申明将在其产品中嵌入Java技术;

1996年9月,约8.3万个网页应用了Java技术来制作;

1997年2月18日,JDK1.1发布;

1997年4月2日,JavaOne会议召开,参与者逾一万人,创当时全球同类会议纪录;

1997年9月,JavaDeveloperConnection社区成员超过十万;

1998年2月,JDK1.1被下载超过2,000,000次;

1998年12月8日,Java 2企业平台J2EE发布 (J2EE1.2);

1999年6月,SUN公司发布Java三个版本:标准版(J2SE)、企业版(J2EE)和微型版(J2ME);

2000年5月8日,JDK1.3发布;

2000年5月29日,JDK1.4发布;

2001年6月5日,Nokia宣布到2003年将出售1亿部支持Java的手机;

2001年9月24日,J2EE1.3发布;

2002年2月26日,J2SE1.4发布,此后Java的计算能力有了大幅提升;

2004年9月30日,J2SE1.5.0发布,成为Java语言发展史上的又一里程碑。为了表示该版本的重要性,J2SE1.5更名为Java SE 5.0;

2005年6月,JavaOne大会召开,SUN公司公开Java SE 6。此时,Java的各种版本已经更名,以取消其中的数字"2": J2ME更名为Java ME, J2SE更名为Java SE, J2EE更名为Java EE;

2006年12月,SUN公司发布JRE6.0;

2009年12月,SUN公司发布Java EE 6;甲骨文(oracle)收购SUN,交易高达价格74亿

2010年11月,由于甲骨文对Java社区的不友善,因此Apache扬言将退出JCP;

2011年7月,甲骨文发布Java SE 7;

2014年3月,甲骨文发表Java SE 8;

2016年9月,Java SE 9 Oracle宣布 发布
...
...
...
...
2019年3月  Java SE  12已经出了。。。

5.不同版本详细说明:
JDK Version 1.1

   于1997-02-19发行。
   引入的新特性包括:
   引入JDBC(Java Database Connectivity);
   支持内部类;
   引入Java Bean;
   引入RMI(Remote Method Invocation);
   引入反射(仅用于内省)。


J2SE Version 1.2

   开发代号为Playground(操场),于1998-12-08发行。
   引入的新特性包括:
   引入集合(Collection)框架;
   对字符串常量做内存映射;
   引入JIT(Just In Time)编译器;
   引入对打包的Java文件进行数字签名;
   引入控制授权访问系统资源的策略工具;
   引入JFC(Java Foundation Classes),包括Swing 1.0、拖放和Java 2D类库;
   引入Java 插件;
   在JDBC中引入可滚动结果集、BLOB、CLOB、批量更新和用户自定义类型;
   在Applet中添加声音支持。


J2SE Version 1.3

   开发代号为Kestrel(红隼),于2000-05-08发行。
   引入的新特性包括:
   引入Java Sound API;
   jar文件索引;
   对Java的各个方面都做了大量优化和增强。


J2SE Version 1.4

   开发代号为Merlin(隼),于2004-02-06发行(首次在JCP下发行)。
   引入的新特性包括:
   XML处理;
   Java打印服务;
   引入Logging API;
   引入Java Web Start;
   引入JDBC 3.0 API;
   引入断言;
   引入Preferences API;
   引入链式异常处理;
   支持IPv6;
   支持正则表达式;
   引入Image I/O slot machine API。


Java Version SE 5.0

   开发代号为Tiger(老虎),于2004-09-30发行。
   引入的新特性包括:
   引入泛型;
   增强循环,可以使用迭代方式;
   自动装箱与自动拆箱;
   类型安全的枚举;
   可变参数;
   静态引入;
   元数据(注解);
   引入Instrumentation。


Java Version SE 6

   开发代号为Mustang(野马),于2006-12-11发行。
   引入的新特性包括:
   支持脚本语言;
   引入JDBC 4.0 API;
   引入Java Compiler API;
   可插拔注解;
   增加对Native PKI(Public Key Infrastructure)、Java GSS(Generic Security Service)、Kerberos和LDAP(Lightweight Directory Access Protocol)的支持;
   继承Web Services;
   做了很多优化。


Java Version SE 7

   开发代号是Dolphin(海豚),于2011-07-28发行。
   引入的新特性包括:
   switch语句块中允许以字符串作为分支条件;
   在创建泛型对象时应用类型推断;
   在一个语句块中捕获多种异常;
   支持动态语言;
   支持try-with-resources;
   引入Java NIO.2开发包;
   数值类型可以用2进制字符串表示,并且可以在字符串表示中添加下划线;
   钻石型语法;
   null值的自动处理。


Java Version SE 8

   开发代号是Spider(蜘蛛),于2014-03-18发行。
   支持 lambda支持;
   增强日期与时间API的功能;
   对垃圾回收的性能也进行了改进;
   并且移除了permgen区。
   Lambdas表达式与Functional接口
   接口的默认与静态方法
   方法引用
   重复注解
   更好的类型推测机制
   扩展注解的支持


每个版本都有更新:      扩展:SUN的衰退

Sun Microsystems, Inc.创立于1982年,名称来自于一个 Stanford University Network的项目,中国台湾地区会译为升阳。是Google的学长。
首先说,如果Sun要在自己的行业加冕桂冠的话,必要条件是踩着八大金刚里谁的尸体呢?Sun不是专门卖软件,Microsoft,Oracle排除,不是网络设备,Cisco排除,不是专门做芯片Intel,Qualcomm排除,也不是互联网,同门师弟的Google排除,更不是个人电子消费,Apple排除,还剩……IBM,是的,相当一段时间里,Sun的业务和IBM的业务高度重合……以卖服务器为核心,存储和解决方案为辅,其它周边杂七杂八一大堆。IBM有自己的Power芯片,Sun有SPARC,IBM有AIX操作系统,Sun有Solaris,然后IBM有DB2数据库,呃,但是Sun拥有Java开发语言,在互联网史前,芯片、操作系统、数据库、开发语言(平台、框架),整体解决方案齐活啦。虽然两军某些装备吨位略有差异,但是还是可以背水一战的。Sun一直对自己比IBM少的那个东西念念不忘,结果是……后面确实有回响。
为什么说Sun有机会挑战蓝色巨人的地位,上面我们已经看到Sun当时没有成熟的数据库,但是这个问题对Sun的困扰其实很小的,证据就是Oracle的存在,如果基于DB2的解决方案能做到独孤求败的话,也就没Oracle什么事了,而且在ERP领域,Oracle从无到有不仅完胜IBM,还对SAP的地位产生了极大挑战,导致SAP收购了Sybase,加强防守,怎么扯这么远,是的,世界很小的,就这么几个玩家。IBM的产品还是基本把持银行、金融领域(基于DB2的黏性起了不小作用),但是亲身经历学校的工作站,公司的小型机都是采用Sun的SPARC。Sun虽然当时没有像样的数据库,但是有一个很强大的“队友”,比IBM吨位稍差,仅此而已。
Sun在1995年发明了Java语言,有人可能不太明白,觉得语言又卖不了钱,新推出的语言一般都是求着开发者去使用,是的语言确实卖不了钱,English这门语言是公开的,不是商品,但是服务和解决方案是要收钱的啊亲!对于从事其它行业的知友,可以查询一下英国在服务咨询行业因为语言优势获得的收益,类似这样思考一下。所有的语言都有:传染性,一旦取得一定优势之后,这门语言是好是坏已经没有人关心了,只要想进来玩这个游戏,大家就都得讲这种语言,语言也是一种生态系统的载体。那么这个Java本身的潜质怎么样呢,可以用“横空出世,后无来者”来形容,这个不能说的太细,马上就打起来了(比如有人会说php必须是最好的语言),程序员之间相互评论对方的语言,就像是不同的大夫评论彼此的处方一样,是非常不文明的行为,有时候更像不同教徒评论对方信仰?但是毋庸置疑的是:之前的语言没做到的特性它做到了并且推向了极致,比如面向对象和泛型(喏,面向对象就是把女友安排在屏幕后面坐,据信可以激活干劲大幅提高工作效率,也有人认为分散注意力,增加了bug&defect,但是,对象,有就比没有强);后面的语言做到的都能在之前已经存在的语言里找到影子,没有颠覆性的创新出现。Google在对外举办的编程竞赛中,一般只推荐C/C++,Java,Python实现,在这三种语言中(不好意思,没有php)只有Java的专利直接属于一个充满想象的商业组织,所以Java对Sun是一个巨大的优势,Java平台叫嚣乎东西,隳突乎南北,企业级,桌面级,移动式,嵌入式,Web端……会各种姿势,都可以生存。即使这种技术放在今天看来,也是激动人心的,设想你可以推出一个App,同时无缝支持Web,Mobile,Pad,汽车Dashboard,当然还有Desktop,Laptop,和你实验室里的工作站,是不是有点虚了,这算什么,你在安装Java的时候,它会明确告诉你,Java已经存在于蓝牙和DVD播放器了。Sun先发制人搞了这么个好东西,对手各种羡慕嫉妒恨是难免的,Bill Gate敏锐的商业嗅觉意识到危险来了,必须拿出打网景的架势来反击Java,不然Java搞在了用户和Windows中间,谁还在乎Java后面是Windows还是M!uqoms呢,于是微软很没节操地搞了个J++/Visual J#微软版Java,试图控制住开发者和用户在Windows平台的Java入口,Sun岂会坐视不理,法庭上见,结果中间Sun遇到财务上的问题,微软说咱别折腾了,我赔点钱,就了了吧,Sun当时基本答应了,此时就看出Sun已经开始出现不小问题了,以至于在战略级产品布局方面做出让步,或者另一种可能就是脑子烧坏了。但是!上面那些只是Blueprint而已!结果是,Sun把Java做得很不好或者不够好,随便怎么说,反正就是没做到想要的效果,不是颠覆性的创新和设计、开发的失败,可以说是运营得很不好。
Sun是一家极具创新能力的公司,Java最初是在1991年开始为交互式电视类似机顶盒什么东西开发的,当时,这东西有点超前,硬件产业什么的跟不上,不能为A厂的机顶盒开发一遍App,再给B生产的再开发一遍,整合产业怎么搞呢,那就用一个转换插头全部变为USB接口,用户只用一个插头,尽情换USB数据线的手机,世界清净了,就是基于这种相似的思想,使得Java具有“一次编译,到处运行”的特性,解救万千开发者于水火之中。即使今天Sun已经不在了,但是Java还在,Java Family还在,Android,这一最具想象力的新平台,具有Java的血统和基因,Sun的创新和贡献对IT工业界影响重大,Sun没能为Java做到的,Google给Java的后代做到了。Sun开发的各种领先技术分布于存储系统、文件系统,还有OpenOffice套件(打击微软Office的),开发工具等等。Sun的创新还体现在另一处:他们在近三十年前就意识到 网络即是计算机,网络作为单独的研究对象,它具有计算能力,存储能力,这活脱脱就是互联网乃至云计算的思维啊亲!后来大家也知道了,真正云计算这个名词开始兴起的时候,2010年Oracle以$74亿收购了Sun,而Sun历史最高市值在$2000亿左右.
而Sun在之前的2008年$10亿收购了MySQL,摆脱了产品线布局缺位,但是MySQL跟DB2 Oracle,甚至是Sybase,MSSqlServer都不是一个等级,$10亿收购MySQL绝对败笔,MySQL带来的收益是否有购价的百分之一都值得怀疑(不查报表了,传统行业不会用MySQL,互联网公司没有几个会花钱在MySQL身上,即使有的:国内某最大的电商也是向第三方MySQL专业购买的支持而不是MySQL的持有者Oracle)
Sun没能利用Java构建一个强有力、可变现的生态系统,没打好Java这张牌。他们没能成功构建这个生态系统,不好到什么程度呢?Java初期的版本在当时的硬件条件下性能确实不太好,尤其涉及到图形的,虽然跨平台的Java很爽,但是图形周边的问题解决起来肯定很困难,Native的图形当年都做了这么长时间才捯饬出来,但是Sun的不努力连IBM都看不下去了,IBM为Java做了一套图形库SWT,送给大家用, 作为Sun的AWT的替代品。Java是Sun的,但是Sun自己开发的IDE还没有IBM给Java开发的好用,前者Netbean,到今天几乎无人问津了,而后者Eclipse则是门庭若市(看一下这个名字,日蚀,IBM对Sun赤裸裸地挑衅),不但作为Java的第一IDE,而且扩展成一个平台了,Sun就是没有能够将Java作为生死攸关的战略产品来做
那么,是否是Sun没有打败IBM,还是IBM打败了Sun呢,都不是,是Sun自己被淘汰了,是IBM战胜了自己,IBM在90年代初期也是一直处在亏损当中,直到93年Gerstner抵达IBM开始商业&市场方面的运作,把IBM从重点为硬件变为转向提供解决方案&咨询服务的公司才起死回生,纯做硬件的要被做软件和服务咨询的搞死,搞软件的会被搞互联网服务的慢慢搞死,Sun至死没能实现转型,没有出现和引入商业&市场方面的领袖人物,倒是为Google输送了不少技术方面的人才。
Sun Microsystem Inc.有机会通过技术上的Java平台和商业上的公司转型这两个大杀器实现华丽转身甚至傲视江湖,可是它没有像Microsoft运作.Net平台和IBM操作公司转型这方面的能力,导致其只能留给后人一声叹息!
Sun Microsystem Inc.倒下的时候还有未竟的事业,还有理想和心愿!
“我猜人生就是教会我们不断的学会放下,遗憾的是最后我们都没有好好的说再见!”

 Java体系结构

J2ME
J2ME--Java 2 Micro Edition用于嵌入式系统开发,如手机和PDA的编程
2000年12月,Sun公司宣布,它将推出Java2平台Micro(J2ME)开发版和适用于Palm OS平台的MID(Mobile Information Device)规范概要。这些新品的推出将使250多万Java技术开发商更容易为通用的Palm OS平台创建应用程序。此外,Sun和Palm公司还将通过JCP(Java CommunityProcess)项目与业界的其它专家一起为个人数字助理(PDA)确定编程接口的技术规范。开发者因为能把他们的Java技术经验用在Palm OS平台上配置解决方案而受益;终端用户因为能将采用J2ME编写的应用程序用于新的企业,商务,娱乐和通信等解决方案而受益。有了相对于Palm OS平台的Java技术发展规划,开发商们将会拥有标准化的适用于业界应用的解决方案。

J2SE
J2SE Java的标准版本 (Java2 Standard Edition) 定位在客户端,主要用于桌面应用软件的编程(GUI)
J2SE--Java 2 Standard Edition 用于工作站,PC机的Java标准平台。
在Java2平台JDK1.2发布之后,Sun公司又相继发布了j2sdk1.3,j2sdk1.3.1,2001年9月发布了j2sdk1.4Beta2版。他们都是支持式计算的免
费的Java2标准平台。Java2标准平台体现了Sun公司的开放精神,被称为"互联网上的世界语",公布于互联网上供大家免费享用,甚至连源代码也不保密,可以在网上免费下载。

J2EE
企业版本(Java2 Enterprise Edition)定义在服务器端Java2的企业版,主要用于分布式网络程序的开发,如电子商务网站
J2EE--Java2 Enterprise Edition可扩展的企业级应用Java2平台。
2001年1月,Sun公司在旧金山召开了关于Java2平台企业版(J2EE)的新闻发布会。J2EE是分布式企业软件组件架构的规范,具有Web性能,具有更高的特性,灵活性,简化的集成性,便捷性,以及J2EE服务器之间的互操作性。目前已有9个取得J2EE技术许可的公司推出了基于J2EE技术的兼容性产品。这些公司都通过了J2EE兼容性测试(CTS)中的各项测试,满足了J2EE技术品牌中的所有要求。当前,有25个公司持有J2EE平台的许可证,他们代表了应用服务器市场的76%~90%的厂商。
SUN MicroSystem 公司总裁 Scott McNealy 认为 Java 为 Internet 和 WWW 开辟了一个崭新的时代。 Java 的诞生必将对整个计算机产业产生深远的影响!

 
不同版本根本区别:
类的不同---》应用领域不同!

Java特点 

Java语言的主要特点:
Java语言有下面一些特点 :简单、面向对象、分布式、解释执行、鲁棒、安全、体系结构中立、可移植、高性能、多线程以及动态性。

1.面向对象

Java语言的设计集中于对象及其接口 ,它提供了简单的类机制以及动态的接口模型。对象中封装了它的状态变量以及相应的方法 ,实现了模块化和信息隐藏 ;而类则提供了一类对象的原型 ,并且通过继承机制 ,子类可以使用父类所提供的方法 ,实现了代码的复用。

2.分布性

Java是面向网络的语言。通过它提供的类库可以处理 TCP/IP协议 ,用户 可以通过 URL地址在网络上很方便地访问其它对象。

3.简单性

Java语言是一种面向对象的语言 ,它通过提供最基本的方法来完成指定的任务 ,只需理解一些基本的概念 ,就可以用它编写出适合于各种情况的应用程序。 Java略去了运算符重载、多重继承等模糊的概念 ,并且通过实现自动垃圾收集大大简化了程序设计者的内存管理工作。另外 ,Java也适合于在小型机上运行 ,它的基本解释器及类的支持只有 40KB左右 ,加上标准类库和线程的支持也只有 215KB左右。库和线程的支持也只有 215KB左右。

4.鲁棒性

Java在编译和运行程序时 ,都要对可能出现的问题进行检查 ,以消除错误的产生。它提供自动垃圾收集来进行内存管理 ,防止程序员在管理内存时容易产生的错误。通过集成的面向对象的例外处理机制 ,在编译时,Java提示出可能出现但未被处理的例外 ,帮助程序员正确地进行选择以防止系统的崩溃。另外,Java在编译时还可捕获类型声明中的许多常见错误 ,防止动态运行时不匹配问题的出现。

5.可移植性

与平台无关的特性使 Java程序可以方便地被移植到网络上的不同机器。同时 ,Java的类库中也实现了与不同平台的接口 ,使这些类库可以移植。另外,Java编译器是由 Java语言实现的 ,Java运行时系统由标准 C实现 ,这使得Java系统本身也具有可移植性。

6.体系结构中立

Java解释器生成与体系结构无关的字节码指令 ,只要安装了 Java运行时系统 ,Java程序就可在任意的处理器上运行。这些字节码指令对应于 Java虚拟机中的表示 ,Java解释器得到字节码后 ,对它进行转换 ,使之能够在不同的平台运行。

7.安全性

用于网络、分布环境下的 Java必须要防止病毒的入侵。 Java不支持指针,一切对内存的访问都必须通过对象的实例变量来实现 ,这样就防止程序员使用"特洛伊 "木马等欺骗手段访问对象的私有成员 ,同时也避免了指针操作中容易产生的错误。

8.解释执行

Java解释器直接对 Java字节码进行解释执行。字节码本身携带了许多编译时信息 ,使得连接过程更加简单。

9.动态性

Java的设计使它适合于一个不断发展的环境。在类库中可以自由地加入新的方法和实例变量而不会影响用户程序的执行。并且 Java通过接口来支持多重继承 ,使之比严格的类继承具有更灵活的方式和扩展性。

10.多线程

多线程机制使应用程序能够并行执行 ,而且同步机制保证了对共享数据的正确操作。通过使用多线程 ,程序设计者可以分别用不同的线程完成特定的行为 ,而不需要采用全局的事件循环机制 ,这样就很容易地实现网络上的实时交互行为。

11.高性能

和其它解释执行的语言如 BASIC、 TCL不同 ,Java字节码的设计使之能很容易地直接转换成对应于特定CPU的机器码 ,从而得到较高的性能。


一句话:java很好!

但是,并不是说学习了java,以后所有的东西都要用java开发了:

某些领域其他语言有更出色的表现,比如,Objective C和后来的Swift在iOS设备上就有着无可取代的地位。浏览器中的处理几乎完全由JavaScript掌控。Windows程序通常都用C++或C#编写。Java在服务器端编程和跨平台客户端应用领域则很有优势。

只能说,不同的语言之间,平分秋色!

Java核心机制

跨平台原理(虚拟机)

【1】跨平台原理理解:

 

 【2】总结:
1.Java运行过程
Java程序的运行分为两步:先编译再解释执行
通过“编译器”将Java源程序编译成Java 字节码文件(.class)(字节码文件采用结构中立的中间文件格式)
通过不同的“虚拟机”将Java字节码文件解释为对应机器语言并执行 


总结2:Java跨平台和C跨平台的区别
Java:一次编译,到处运行    
C:多次编译,到处运行
在互联网情况下,平台各异,Java的跨平台更具有优势
Java可以跨所有平台吗:要看有没有提供并安装相应的虚拟机
Java的运行速度没有C语言快:Java需要将class文件解释成机器码再执行;C直接执行机器码 

总结3:字节码文件bytecode
.class文件  二进制文件
格式中立、平台无关的二进制文件
是编译的产物,是解释的原料

总结4:Java虚拟机 JVM
JVM是Java Virtual Machine(Java虚拟机)的缩写
JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
JVM就是一个虚拟的用于执行bytecodes字节码的计算机
Java虚拟机是Java最核心技术,也是跨平台的基础。
Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够“一次编译,到处运行”的原因

Java跨平台原理

http://www.cnblogs.com/gw811/archive/2012/09/09/2677386.html

此篇博文主要源自网络xiaozhen的天空的博客:http://xiaozhen1900.blog.163.com/blog/static/1741732572011325111945246/

 

垃圾收集机制

       垃圾收集的目的在除不再使用的对象,当对象建立的时候垃圾收集期,就开始监控对象的动态情况,垃圾收集主要是对内存的释放。创建对象的时候申请一个空间
    1.不再使用的内存空间应回收---》垃圾收集;
    2.Java消除了程序员回收无用内存空间的职责;提供一种系统级线程跟踪存储空间的分配情况。在JVM的空闲时,检查并释放可被释放的存储器空间;相比c++,开发人员负责要自己收回无用内存。
    3.垃圾收集在Java程序运行过程中自动进行,程序员无法精确控制和干预;
    4.GC的自动回收,提高了内存空间的利用效率,也提高了编程人员的效率,很大程度上减少了因为没有释放空间而导致的内存泄露。 


常用DOS命令

【1】DOS操作系统
--Microsoft公司推出的操作系统。(在windows之前的操作系统)
--DOS是英文"Disk Operating System"的缩写,其中文含意是"磁盘操作系统".
--DOS是单用户、单任务的操作系统.(只能执行一个任务)

 【2】DOS命令
--在windows中,我们通过鼠标菜单等来操作系统,而在dos操作系统中,要通过dos命令来操作系统。
--是DOS操作系统的命令,是一种面向磁盘的操作命令,
--不区分大小写。
【3】命令学习:
windows给我们保留了类似dos系统的操作界面,可以直接操作磁盘!

 

 

 

 

 Java环境准备

【1】官网:
Oracle公司为Linux、Mac OS X、Solaris 和Windows提供了Java 开发工具包( JDK)的最新、最完整的版本。
要想下载Java开发工具包,可以访问Oracle网站:
     https://www.oracle.com/technetwork/java/javase/downloads/index.html

 

 JDK、JRE、JVM三者间的关系  

JDK(Java Development Kit)是针对Java开发员的产品,是整个Java的核心,包括了Java运行环境JRE、Java工具和Java基础类库。Java Runtime Environment(JRE)是运行JAVA程序所必须的环境的集合,包含JVM标准实现及Java核心类库。JVM是Java Virtual Machine(Java虚拟机)的缩写,是整个java实现跨平台的最核心的部分,能够运行以Java语言写作的软件程序。

 在计算机开发语言的历史中,从来没有哪种语言象Java那样受到如此众多厂商的支持,有如此多的开发工具。

JDK(Java Development Kit)
  JDK是Java开发工具包,是Sun Microsystems针对Java开发员的产品。
  JDK中包含JRE,在JDK的安装目录下有一个名为jre的目录,里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib和起来就称为jre。
  JDK是整个JAVA的核心,包括了Java运行环境JRE(Java Runtime Envirnment)、一堆Java工具(javac/java/jdb等)和Java基础的类库(即Java API 包括rt.jar)。
  ①SE(J2SE),standard edition,标准版,是我们通常用的一个版本,从JDK 5.0开始,改名为Java SE。
  ②EE(J2EE),enterprise edition,企业版,使用这种JDK开发J2EE应用程序,从JDK 5.0开始,改名为Java EE。
  ③ME(J2ME),micro edition,主要用于移动设备、嵌入式设备上的java应用程序,从JDK 5.0开始,改名为Java ME。

  Java Runtime Environment(JRE)
  是运行基于Java语言编写的程序所不可缺少的运行环境。也是通过它,Java的开发者才得以将自己开发的程序发布到用户手中,让用户使用。
  RE中包含了Java virtual machine(JVM),runtime class libraries和Java application launcher,这些是运行Java程序的必要组件。
  与大家熟知的JDK不同,JRE是Java运行环境,并不是一个开发环境,所以没有包含任何开发工具(如编译器和调试器),只是针对于使用Java程序的用户。
 
  JVM(java virtual machine)
  就是我们常说的java虚拟机,它是整个java实现跨平台的最核心的部分,所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。
  也就是说class并不直接与机器的操作系统相对应,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。
  只有JVM还不能成class的执行,因为在解释class的时候JVM需要调用解释所需要的类库lib,而jre包含lib类库。
  JVM屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。

安装notepad++

 

第一个Helloword 

 

 

 常见问题

【1】低级错误:单词写错
【2】大小写严格区分:
【3】类名和源文件的名字必须一致
【4】语法错误
【5】符号:成对编程:''  ""  ()  {}  [] <>
【6】符号:必须是英文状态下的
【7】main方法格式固定:
        public static void main(String[] abc){}
【8】语法:
        javac HelloWorld.java
        java HelloWorld

常用编译执行方法

 API

API:java中的一个帮助文档,帮助我们查看java的内容的。
使用说明,词典--帮助我们理解的

编程风格

 

全文格式:Ctrl+a——>Ctrl+alt+L 

java注释

【1】注释:标注解释:
【2】分类:
(1)单行注释:  //
(2)多行注释:   /*     */
(3)文档注释:/**    */
讲解:
利用javadoc命令生成程序对应的API
文档注释可以帮助在API中进行各种解释的。

 

 【3】注释作用:
(1)对代码进行解释说明
(2)代码的调试,错误的排查(排除法)
【4】注释对代码的执行是否有影响?没有
与大多数程序设计语言一样,Java 中的注释也不会出现在可执行程序中。因此,  可以在源程序中根据需要添加任意多的注释,而不必担心可执行代码会膨胀。
利用反编译工具证明:
从.java到.class的编译过程中,注释并没有编译到字节码文件中去,所以更加不会影响后续代码的执行。

反编译工具使用

//下面是一个类,类名:HelloWorld2
public class HelloWorld2{
        //程序的入口:
        public static void main(String[] args){
                //功能:进行自我介绍:
                System.out.print("姓名:");
                System.out.println("\tzhaoss");
                System.out.print("职业:");
                System.out.println("\t程序员");
                
                
                System.out.println("111111111111111111111");
                System.out.println("aaaaa\tbbbb\nbb");
                /*
                1.print和println的区别:
                  print:将""中的内容原样输出+不换行
                  println:将""中的内容原样输出+换行
                2.转义字符:\  将后面的普通字母转换成为其他的含义:
                        \t:一个制表符   8格
                        \n:换行
                3.在一个源文件中,可否有多个类?
                在一个源文件中,可以有多个类,但是只能有一个类被public修饰。
                只有跟源文件名字相同的类才可以被public修饰。
                每个类都会生成自己的字节码文件,互不影响。
                */
        }
}
class Demo01{
        public static void main(String[] args){
                System.out.println("demo01...");
        }
}
class Demo02{
        public static void main(String[] args){
                System.out.println("demo02...");
        }
}

2、数据类型

标识符

【1】标识符:读音   biao zhi fu
【2】什么是标识符? 
  包,类,变量,方法.....等等,只要是起名字的地方,那个名字就是标识符
【3】标识符定义规则:
1.四个可以:数字,字母,下划线(_),美元符($)
PS:这个字母表示的含义比较宽泛:字母,汉字,日语,俄语都行,
但是一般我们起名字,都是利用字母,并且利用的是英文,不是拼音。nianLing
因为:Java不采用通常语言使用的ASCII字符集,不是只支持英文的,而是采用unicode这样的标准的国际字符集。因此,这里的字母的含义:英文、汉字等等。(但是不建议大家使用汉字来定义标识符!)
2.两个不可以:不可以数字开头,不可以使用java中关键字
3.见名知意:见到名字就大致知道什么意思
4.大小写敏感  int a=10;  int A=10;
5.驼峰命名
      类名:HelloWorld  :首字母大写+驼峰命名
      方法名,变量名:helloWorld   首字母小写+驼峰命名
      包名:  全部小写com.bjsxt.test01
6.长度无限制,但是不建议太长    int stu=10;

关键词

编码和字符集

 

 

 
0,1代表 1位
1字节=8位
1字符=2字节=16位

扩展:字符集和字符编码

http://字符集和字符编码(Charset & Encoding)

变量和常量

举例:
我的年龄:17---》18---》19---》20----》21
年龄:不断的变化----》变量
17
18
19 ----->常量 :
变量是变化着的一个数,在变化的每个阶段上的数值是一个常量。

【1】常量变量定义
在程序中存在大量的数据来代表程序的状态,
其中有些数据在程序的运行过程中值会发生改变,
有些数据在程序运行过程中值不能发生改变,
这些数据在程序中分别被叫做变量和常量。

【2】变量举例:
在2D游戏程序中,需要代表人物的位置,则需要2个变量,一个是x坐标,一个是y坐标,在程序运行过程中,这两个变量的值会发生改变
【3】常量分类:字面常量,字符常量
(1)字面常量:18,6.9等
(2)字符常亮:PI
代表常数,便于程序的修改(例如:圆周率的值)
增强程序的可读性(例如:常量UP、DOWN、LEFT和RIGHT分辨代表上下左右,其数值分别是1、2、3和4)

字面常量

【1】字面常量有哪些类型:

【1】变量的学习:
声明格式为:
type  varName  [=value] [{,varName[=value]}] ;
(1)变量的声明:
(2)变量的赋值:

                //1.变量的声明

                //以年龄为例:
                int age;//声明了一个变量,名字是age,类型是int类型
                //System.out.println("age="+age);出错,没有初始化
                
                //局部变量(放在方法中的变量)必须进行初始化,必须赋值。
                //2.变量的赋值
                age = 19;
                
                //将声明和赋值写在一起:int age=19;                
                
                //int age=21;变量的重复定义,直接报错。
                age=21;
                System.out.println("age="+age);

 (3)变量的使用:

                int a=10;
                int b=20;
                int c=a+b;

利用javap -c  字节码文件名  这个命令,来执行 “反汇编”过程:

 

 (5)习题:

public class TestVar03{
        public static void main(String[] args){
                int num1=10;
                int num2;
                num2=30;
                num1=num2+num1;
                num1=num2;
                num2=num1-4;
                num2=num1;
                System.out.println("num1="+num1);
                System.out.println("num2="+num2);
        }
}

 (5)变量的作用域:

public class TestVar04{
        
        int c=30;//成员变量:在类中,方法外的变量
        
        
        public static void main(String[] args){
                System.out.println(a);//不能
                int a=10;//局部变量:在方法中
                System.out.println(a);//能
                System.out.println(b);//不能
                System.out.println(c);//能
                if(1==1){
                        int d=80;
                        System.out.println(d);//能
                }
                System.out.println(d);//不能
                int d=30;
                System.out.println(d);//能
        }
        
        public void eat(){
                int a=10;
                System.out.println(a);//能
                int b=20;
                System.out.println(c);//能
        }
}
/*
作用域:作用范围:离它最近的{}
*/

基本数据类型

 整数类型

【1】整型常量
十进制整数,如:99, -500, 0
八进制整数,要求以 0 开头,如:015
十六进制数,要求 0x 或 0X 开头,如:0x15
二进制:

进制:逢几进1  :
二进制:0,1,10,11,100......
八进制:0,1,2,3,4,5,6,7,10
十进制:0,1,2,3,4,5,6,7,8,9,10,11,,,,,,
十六进制:0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,10,,,,

计算机用的就是二进制。
人类用十进制。

 【3】代码练习:

public class TestVar05{
        public static void main(String[] args){
                //在java中整数类型默认都是int类型的,比如你写一个12,其实就是int类型的12
                //声明变量:
                byte b=10;//超出表示范围会出错。
                System.out.println(b);
                short s=30000;
                System.out.println(s);
                int i1=12;//十进制
                System.out.println(i1);
                int i2=012;//八进制
                System.out.println(i2);//10----》表面上看是几进制,但是实际参与到运算中都是十进制在参与运算
                int i3=0x12;//十六进制
                System.out.println(i3);//18
                int i4=0b11;//二进制
                System.out.println(i4);//3
                //int i5=12345678920;
                //System.out.println(i5);
                long num=12345678920L;
                System.out.println(num);
                //整数类型默认是int类型,要想赋给long类型,后面必须加上L或者l(推荐使用L)
                
                
        }
}

进制转换

 

 

 

 浮点类型

 【3】练习代码:

public class TestVar06{
        public static void main(String[] args){
                //对于一个小数来说,默认是double类型,你要是想把它给float类型,后面必须加上f或者F
                float f1=5.923f;
                System.out.println(f1);
                float f2=37.23445656778f;
                System.out.println(f2);
                double d1=3.456;
                System.out.println(d1);
                double d2=2.34545656878980867;
                System.out.println(d2);
                double d3=314E-2;
                System.out.println(d3);
                
                
                //不要进行浮点数的比较:
                float f4=0.3f;//0.29999999999
                double d4=0.3;//0.300000001
                System.out.println(f4==d4);
                /*
                =:赋值:将等号右侧的结果赋予给等号的测试
                ==:判断:判断==左右的值是否相等: 要么相等----》true 要么不相等---->false
        
                */
                 System.out.println(2*3.141592653*8.7);
        }
}

字符类型

单引号用来表示字符常量。例如‘A’是一个字符,它与“A”是不同的,“A”表示含有一个字符的字符串。

char 类型用来表示在Unicode编码表中的字符。

char类型在内存中存储的是该字符的Unicode编码值,所以char类型可以当做int类型来处理。

常用转义字符:

 

 练习代码:

public class TestVar07{
        public static void main(String[] args){
                //字符型表示的是单引号引起来的单个字符,占用两个字节
                char ch1='a';
                char ch2='A';
                char ch3='人';
                char ch4='4';
                char ch5=' ';
                
                
                char ch6='a';
                System.out.println(ch6);//a
                System.out.println(ch6+5);//102
                System.out.println(102-ch6);//5
                //表面上看,字符型表现出来的就是字面含义,字符a表现出来的就是a,但是实际在内存中进行运算
                //或者进行存储的时候,表示的是一个数,这个数是ASCII码、
                System.out.println("-------------------------------");
                char ch7='中';
                System.out.println(ch7);//中
                System.out.println(ch7+70);//20083
                System.out.println(20083-ch7);//70
                //表面上看,字符型表现出来的就是字面含义,字符中表现出来的就是中,但是实际在内存中进行运算
                //或者进行存储的时候,表示的是一个数,这个数是Unicode码(ASCII是Unicode码表的前128位)
                
                
                int a='c';
                System.out.println(a);
                char ch8=99;
                System.out.println(ch8);
                int b=(int)ch8;
                System.out.println(b);
                char ch9=(char)99;
                System.out.println(ch9);
                
                System.out.println("-------------------------------");
                System.out.println("------------转义字符:-------------------");
                //转义字符:/将后面的普通字母转换成为其他的含义:
                char c1='\t';//1.制表符
                char c2='\n';//2.换行
                System.out.println("aaaa"+c1+"bb"+c2+"cc");
                System.out.println("aaaa\tbb\ncc");//字符串就是由1-n个字符组成的
                System.out.println("helloworld");
                System.out.println("aaa\bbbb");//3.\b:退格  
                System.out.println("aaaaa\rbbb");//4.\r:光标回到本行起始位置
                System.out.println("\"你好世界\"");
                System.out.println("“你好世界”");
        }
}

 布尔类型

【1】boolean类型有两个值,true和false

【2】boolean 类型用来判断逻辑条件,一般用于程序流程控制

【3】实践:
请不要这样写:if ( is == true && done == false ) ,只有新手才那么写。
对于任何程序员 if ( is && !done ) 都不难理解吧。
所以去掉所有的==fasle 和 ==true。

代码练习:

public class TestVar08{
        public static void main(String[] args){
                //假如布尔类型,只声明和赋值,那么反编译显示的是true是1,false为0
                //假如布尔类型,声明赋值+使用,那么反编译显示的是true或者false
                //布尔类型占用1位
                boolean flag1=true;
                boolean flag2=false;
                System.out.println("flag1="+flag1);
                boolean a=5==8;
                System.out.println(a);
                boolean b=3<=6;
                System.out.println(b);
                
                //一般布尔类型,结合到控制流程语句中:
                boolean flag=3<7;//flag:true
                if(flag){//true==true--->true
                        System.out.println("第一个数小于第二个数!");
                }else{//flag==false--->true==false--->false
                        System.out.println("第一个数不小于第二个数!");
                }
        }
}

 

 

基本数据类型转换 

【1】什么是类型转换:
在赋值运算,或者算数运算的时候,要求数据类型一致,就要进行类型的转换。

【2】类型转换的种类:
自动转换,强制转换

【3】代码讲解:

public class TestVar09{
        public static void main(String[] args){
                double d=3;
                System.out.println(d);//3.0
                int i=(int)3.7;//直接赋值会出错。
                System.out.println(i);
                /*
                类型转换:
                种类:
                1.自动转换
                2.强制转换
                */
                
                //double d2=12+3002+3.14+'a'+true+7.8f+2398L;
                //double d2=12+3002+3.14+'a'+7.8f+2398L;
                int d2=(int)(12+3002+3.14+'a'+7.8f+2398L);
                System.out.println(d2);
                /*
                1.四类八种类型中,只有布尔类型不能参与运算。
                2.多个类型参与运算,结果为什么类型呢?
                类型级别:[转换方向]
                byte,short,char--->int--->long--->float--->double
                在同一个表达式,假如存在多种类型,要转换成为当前表达中级别最高的那个然后进行运算
                =12+3002+3.14+'a'+7.8f+2398L
                =12.0+3002.0+3.14+97.0+7.8+2398.0=。。。。double类型的数据
                
                
                赋值运算:
                左侧=右侧:直接赋值
                左侧>右侧:直接赋值
                
                左侧<右侧:强制转换
                
                */
                
                //特例:
                byte b=(byte)129;
                byte b2=12;
                System.out.println(b);
                //byte,short,char类型来说,比较特殊,只要在表述范围中,就可以直接赋值不用强转,
                //但是一旦超出表述范围,就要强转
                
                
        }
}

//求圆的周长和面积:
import java.util.Scanner;//到这个位置上找到Scanner这个类。
public class TestVar11{
        public static void main(String[] args){
                //提取变量:以后我要是修改变量的值,只要修改这一个位置即可,后面的代码直接利用变量的名字获取它的数值。
                //圆周率:
                //一个变量被final修饰,这个变量就变成了一个常量,它的值就不可以再被修改了。
                //这个常量:pi----》字符常量       18,19---》字面常量
                //一般有个约定俗称的规定:常量名字全部大写
                final double PI=3.14159;
                //半径:
                
                //键盘录入:
                //获取一个扫描器:
                Scanner sc=new Scanner(System.in);
                System.out.print("请录入一个半径:");
                int r=sc.nextInt();
                //int r=14;
                
                
                
                //圆的周长:
                double c=2*PI*r;
                System.out.println("圆的周长是:"+c);
                
                //圆的面积:
                //PI=9.78;// 错误: 无法为最终变量pi分配值
                double s=PI*r*r;
                System.out.println("圆的面积是:"+s);
                
                
                
                
                
                
        }
}

3、运算符

【1】Java 语言支持如下运算符:
算术运算符:  +,-,*,/,%,++(自增),--(自减)
赋值运算符 =  
扩展赋值运算符:+=,-=,*=,/=
关系运算符:  >,<,>=,<=,==,!=
逻辑运算符:  &&,||,!,&,|,^
位运算符:  &,|,^,~ , >>,<<,>>> (了解!!!)
条件运算符 ?:
【2】相关概念辨析
+        运算符  操作符         Operator
5+6    表达式                     expression
5  6     操作数                     Operand
int m =5+6;    语句             Sentence

算法运算符

【1】

public class TestOpe01{
        public static void main(String[] args){
                //  /除法:  %:取余数
                System.out.println(10/3);//3
                System.out.println(10%3);//1
                System.out.println(10/3.0);//3.3333
                System.out.println(10%3.0);//1.0
                
                //键盘录入一个四位数,分别输出每位上的数字:
                int num=6789;
                //个位:
                int num1=num%10;  ///6789--->9
                //十位:
                int num2=num/10%10;  //6789--->678--->8
                //百位:
                int num3=num/100%10;//6789---->67---->7		
                //千位:
                int num4=num/1000;//6789---->6		
                System.out.println(num1+"\t"+num2+"\t"+num3+"\t"+num4);
        }
}

【2】

public class TestOpe02{
        public static void main(String[] args){
                /*
                +:
                1.正数
                2.求和
                3.字符串的拼接
                */
                System.out.println(+5);
                System.out.println(5+6);
                System.out.println(5+'a');
                System.out.println(5+"a");
                System.out.println(5+6+"a");//11+"a" --->字符串跟任何类型相加结果都会拼为一个字符串 --->11a
                System.out.println("a"+5+6);//"a5"+6--->a56
        }
}

【3】

public class TestOpe03{
        public static void main(String[] args){
                //++
                int a=5;
                a++;//a=a+1;
                System.out.println(a);
                
                a=5;
                ++a;//a=a+1;
                System.out.println(a);
                //在++单独运算的时候,就是加1操作,
                
                
                
                //只要参与到运算中,就必须遵照规律:
                //a++:先运算,后加1
                //++a:先加1,后运算
                a=5;
                int m=a++ +4;// m=a+4   a=a+1
                System.out.println(a);//6
                System.out.println(m);//9
                
                
                a=5;
                int n=++a+4;//a=a+1  n=a+4
                System.out.println(a);//6
                System.out.println(n);//10
                
                a=5;
                System.out.println(a++ +a++);
                System.out.println(a++ + ++a);
                System.out.println(++a+a++);
                System.out.println(++a+ ++a);
                
        }
}

 赋值运算符

【1】赋值运算符:=
引入一个中间变量:

public class TestOpe04{
        public static void main(String[] args){
                int a=10;
                int b=20;
                System.out.println("交换前:"+a+"----"+b);
                //交换:
                int t;
                t=a;
                a=b;
                b=t;
                //输出交换后的数:
                System.out.println("交换后:"+a+"----"+b);
        }
}

【2】扩展赋值运算符:+=,-=,*=,/=

public class TestOpe05{
        public static void main(String[] args){
                int a=10;
                int b=20;
                //按照java中的逻辑写:
                int sum=0;
                //sum=sum+a;
                sum+=a;
                //sum=sum+b;
                sum+=b;
                System.out.println(sum);
        }
}

扩展赋值运算符:可读性稍微少一点。,但是编译的效率高。

【3】观察----题:

public class TestOpe06{
        public static void main(String[] args){
                byte a=10;//1
                int b=20;//2
                a+=b; //3 ----->+= 自动帮我们完成强制转化
                a=a+b;//4 -----》必须自己写:a=(byte)(a+b)
                
        }
}
面试题:实现两个整数变量的交换
public class TestSwap {
        public static void main(String[] args) {
                int a = 10;
                int b = 20;		
                System.out.println("a:"+a+",b:"+b);
                
                //方式1:使用第三方变量(开发中用的)		
                int c = a;
                a = b;
                b = c;
                System.out.println("a:"+a+",b:"+b);
                System.out.println("------------");		
                
                //方式2:用位异或实现(面试用)
                //左边:a,b,a
                //右边:a ^ b	
                a = 10;
                b = 20;
                a = a ^ b;
                b = a ^ b; //a ^ b ^ b = a
                a = a ^ b; //a ^ b ^ a = b
                System.out.println("a:"+a+",b:"+b);		
                
                //方式3:用变量相加的做法
                a = 10;
                b = 20;
                a = a + b; //a=30
                b = a - b; //b=10
                a = a - b; //a=20
                System.out.println("a:"+a+",b:"+b);	
                
                //方式4:一句话搞定
                a = 10;
                b = 20;
                b = (a+b) - (a=b); //b=30-20=10,a=20
                System.out.println("a:"+a+",b:"+b);
        }
}

关系运算符

【1】关系运算符:  >,<,>=,<=,==,!=
【2】代码:

public class TestOpe07{
        public static void main(String[] args){
                //>,<,>=,<=,==,!=
                //关系运算符连接的表达式,返回的结果是一个布尔值。要么true,要么false
                //以后应用场合:条件,for等
                System.out.println(5>7);//false
                System.out.println(5<=7);//true
                System.out.println(7<=7);//true
                System.out.println(5==7);//==比较,判断  =赋值
                System.out.println(5!=7);//true
                System.out.println(5<9=='a'>'A');//true==true--->true
        }
}

逻辑运算符

【1】课上代码:
逻辑运算符:  &&,&,||,|,!,^
与或非:

public class TestOpe08{
        public static void main(String[] args){
                //逻辑运算符:左右连接的都是布尔类型的操作数:
                //&----逻辑与:只要操作数中有一个是false,那么结果一定是false
                System.out.println(true&false);
                System.out.println(true&true);
                System.out.println(false&false);
                System.out.println(false&true);
                //&&----短路与:
                /*
                从结果上看,&和&&没有区别:
                但是实际上区别:
                对于短路与来说,只要第一个操作数是false,那么第二个操作数就不会再进行计算了
                */
                System.out.println(true&&false);
                System.out.println(true&&true);
                System.out.println(false&&false);
                System.out.println(false&&true);
                
                
                System.out.println("-----------------------");
                //|----逻辑或:只要操作数中有一个是true,那么结果一定是true
                System.out.println(true|false);
                System.out.println(true|true);
                System.out.println(false|false);
                System.out.println(false|true);
                //||---短路或:
                /*
                从结果上看,逻辑或和短路或的结果是一样的。
                但是区别:
                对于短路或来说,只要第一个操作数是true,那么第二个操作数就不用计算了,结果就直接为true了。
                */
                System.out.println(true||false);
                System.out.println(true||true);
                System.out.println(false||false);
                System.out.println(false||true);
                System.out.println("-----------------------");
                //^  ----异或:相同为false,不同为true
                System.out.println(true^false);
                System.out.println(true^true);
                System.out.println(false^false);
                System.out.println(false^true);
                System.out.println("-----------------------");		
                //!-----非
                System.out.println(!true);//false
                System.out.println(!false);//true
        }
}

三目运算符

import java.util.Scanner;
public class TestOpe10{
        public static void main(String[] args){
                //三目/三元/条件运算符:
                //A?B:C
                //A代表着一个表达式,这个表达式返回的结果要么是true,要么是false
                //假如A返回的是true,那么结果为B
                //假如A返回的是false,那么结果为C
                String str=5<7?"你好":"java";
                System.out.println(str);
                
                //功能:男孩女孩选择晚饭吃什么,要是男孩和女孩的意见一样,听男孩的,要是意见不一样,听女孩的。
                System.out.println("今晚可以选择:1.火锅  2.烧烤  3.烤鱼");
                Scanner sc=new Scanner(System.in);
                System.out.println("男孩选择:");
                int boychoice=sc.nextInt();
                System.out.println("女孩选择:");
                int girlchoice=sc.nextInt();
                /*
                if(boychoice==girlchoice){
                        System.out.println("听男孩的");
                }else{
                        System.out.println("听女孩的");
                }
                */
                System.out.println(boychoice==girlchoice?"听男孩的":"听女孩的");
                
                
                //三元运算符  可以 用来  代替  以后学习的:if-else选择 
        }
}

位运算符

&,|,^跟逻辑运算符长得一样,如何区分呢?
如果左右连接的是布尔类型的操作数---》逻辑运算符
如果左右连接的是具体的数字---》位运算符

有哪些位运算符:
位运算符:  &,|,^,~ , >>,<<,>>>


【1】左移:<<

 

 

 运算符的级别

    级别表:

    不需要去刻意的记优先级关系
赋值<三目<逻辑<关系<算术<单目
理解运算符的结合性
PS:
(1)我一般想要表达复杂的表达式,我就用()
(2)单目:   !,~
    双目:   &,|,+,-
    三目:   ?: 

4、控制流程

分支

if

【1】单分支:

public class TestIf01{
        public static void main(String[] args){
                //功能:随机录入三个数(1-6),求和,根据和的大小选择奖品。
                //三个数
                int num1=3;
                int num2=1;
                int num3=1;
                
                //求和:
                int sum=0;
                sum+=num1;
                sum+=num2;
                sum+=num3;
                
                System.out.println("三个数的和是:"+sum);
                
                //根据和的大小选择奖品
                if(sum>=12)
                        System.out.println("恭喜你,获得了一等奖!");
                    System.out.println("你很幸运啊。。。");
                
                
                
                if(sum>=9&&sum<12){
                        System.out.println("恭喜你,获得了二等奖!");
                }
                
                if(sum>=6&&sum<9){
                        System.out.println("恭喜你,获得了三等奖!");
                }
                
                if(sum<6){
                        System.out.println("谢谢惠顾!");
                }
                
                
                /*
                1.上面的代码中,我写了4个if的分支,每个都是一个单分支,四个单分支组成了四个选择。
                   上面的四个分支,是从上至下顺序执行的,是不可逆的过程。
                2.单分支原理:
                if(){}
                ()中是一个条件表达式,这个表达式返回的结果是要么是true要么是false
                假如返回的是true,就执行后面{}中的代码。假如返回的是false,就不执行后面{}的代码。
                
                3.if后面的{}可以省略不写,但是假如省略了,那么if只负责后面一句话,
                  所以我们一般在自己写代码的时候,建议:写着{} 
                  
                4.单分支缺点:
                我们这道题的代码,是想多个分支里面走一个,所以假如走了一个分支,后面的分支就不想走了,
                按照单分支的特点来说,是要每个都顺序执行的,效率相对较低
                
                5.优化:不用单分支,用多分支:
                
                
                */
                
                
                
        }
}

【2】多分支:

public class TestIf02{
        public static void main(String[] args){
                //功能:随机录入三个数(1-6),求和,根据和的大小选择奖品。
                //三个数
                int num1=3;
                int num2=1;
                int num3=1;
                
                //求和:
                int sum=0;
                sum+=num1;
                sum+=num2;
                sum+=num3;
                
                System.out.println("三个数的和是:"+sum);
                
                //根据和的大小选择奖品
                if(sum>=12){
                        System.out.println("1等奖");
                }else if(sum>=9){//else-->sum<12
                        System.out.println("2等奖");
                }else if(sum>=6){//else--->sum<9
                        System.out.println("3等奖");
                }else{//sum<6
                        System.out.println("末等奖");
                }
                
                /*
                1.if(){}elseif(){}elseif(){}else  这是一条语句,一个多分支有多个选择。
                   并且这些分支里面只走一个,假如走了某个分支,后面的分支就不会再判断不会走了,效率比单分支高。
            2.if    else if   ---》else 隐藏条件:跟上面相反的可能性
                3.建议:建议你写的多分支中有最后的那个else
                  最后的else做一个“兜底”的功能。
                
                
                */
                
                
                
                
        }
}

【3】双分支:

public class TestIf03{
        public static void main(String[] args){
                //功能:随机录入三个数(1-6),求和,根据和的大小选择奖品。
                //三个数
                int num1=3;
                int num2=1;
                int num3=1;
                
                //求和:
                int sum=0;
                sum+=num1;
                sum+=num2;
                sum+=num3;
                
                System.out.println("三个数的和是:"+sum);
                
                //根据和的大小选择奖品
                if(sum>=12){
                        System.out.println("中奖了");
                }else{//sum<12
                        System.out.println("没中奖");
                }
                
                
                System.out.println(sum>=12?"中奖了":"没中奖");
                
        }
}

【5】总结:
(1)单分支
(2)多分支
(3)双分支
(4)随机数
(5)if的嵌套:
if(条件1){
        if(条件2){
                if(条件3){
                        //。。。。。。
                }
        }

}
 

public class TestIf04{
        public static void main(String[] args){
                //录入会员积分,按照积分打折:
                //录入会员积分:
                Scanner sc=new Scanner(System.in);
                System.out.println("请录入你的积分:");
                
                
                //判断:录入的是否是一个int类型的数:
                
                if(sc.hasNextInt()){//hasNextInt()判断录入的是否是一个int类型的数,是返回true,不是返回的是false
                        int credits=sc.nextInt();
                        //判断:
                        if(credits>=5000){
                                System.out.println("6折");
                        }else if(credits>=3000){
                                System.out.println("7折");
                        }else if(credits>=1000){
                                System.out.println("8折");
                        }else{
                                System.out.println("9折");
                        }
                        
                }else{
                        System.out.println("录入错误,必须要录入一个整数!");
                }
                
                
                
                
                
        }
}

 switch

【1】讲解:

public class TestSwitch01{
        public static void main(String[] args){
                //键盘录入学生的成绩,按照成绩划分等级:
                //键盘录入成绩:
                int score=44;
                //按照成绩划分等级
                switch(score/10){
                        case 10:
                        case 9:System.out.println("A级");break;
                        case 8:System.out.println("B级");break;	
                        case 7:System.out.println("C级");break;
                        case 6:System.out.println("D级");break;
                        case 5:
                        case 4:
                        case 3:
                        case 2:
                        case 1:System.out.println("E级");break;
                        default:System.out.println("error");break;
                }
                
                
                
                /*
                1.分支switch后面是一个(),()中返回的是一个等值
                 这个值可以是:byte,int,char,short,JDK1.5之后可以使用枚举,JDK1.7之后,可以使用String
                2.将这个等值依次跟{}中的case后面的数值进行比较:假如满足(匹配),就执行:后面的代码。
                   为了防止“穿透”,每个分支后面要加上一个关键字叫:break
                
                3.也有一个“兜底”功能的分支:default,如果default在最后一行,就不需要加break了,但是要是
                在中间某一行,那么为了防止“穿透”,必须后面加上break
                4.假如相连的某些分支中代码执行一样,那么可以删除只留最后一个即可。
                5.if和switch哪个好?
                switch能解决的问题,if都可以解决。但是if能解决的问题switch不一定能解决。
                if后面的()中可以加等值判断,也可以加区间判断,只要返回true和false即可
                但是switch只能利用等值判断。只能用固定的类型。
                switch:我们的等值判断基本用的switch偏多。
                
                
                
                */
        }
}

【2】代码:

public class TestSwitch02{
        public static void main(String[] args){
                //做一个简单的计算器功能:
                //1.录入第一个数
                Scanner sc=new Scanner(System.in);
                System.out.print("请录入第一个操作数:");
                int num1=sc.nextInt();
                
                //2.录入第二个数
                System.out.print("请录入第二个操作数:");
                int num2=sc.nextInt();
                
                
                //3.录入运算符
                System.out.print("请录入运算符---:+,-,*,/");
                String ope=sc.next();//键盘录入字符串
                
                //4.根据运算符进行计算:
                switch(ope){
                        case "+":System.out.print("结果为:"+(num1+num2));break;
                        case "-":System.out.print("结果为:"+(num1-num2));break;
                        case "*":System.out.print("结果为:"+(num1*num2));break;
                        case "/":
                                        if(num2!=0){
                                                System.out.print("结果为:"+(num1/num2));
                                        }else{
                                                System.out.print("除数不能为0!");
                                        }
                                        break;
                }
        }
}

循环:while、do while、for

【1】while:

public class TestWhile{
        public static void main(String[] args){
                //功能:求和:1+2+3+4+5    
                int i=1;//【1】条件初始化 
                int sum=0;//sum--》接收和的	
                while(i<=5){//【2】条件判断 
                        sum=sum+i;//【3】循环体 
                        i++;//【4】迭代
                }	
                System.out.println("和是:"+sum);	
                /*
                1.什么情况下想到用循环解决问题的:
                   在代码多次有规律重复的情况下
                2.while后面是一个(),这个()中返回的是一个布尔值:true,false
                  在第一次循环的时候,判断()的内容,如果是true就执行{}中内容,
                  在第二次循环以后,每一次循环还是要走这个判断的。
                
                PS:()中要是直接写一个true,就是死循环了。
                
                3.循环执行过程:
                最开始:i=1   sum=0
                第1次循环:i<=5---》满足,执行:sum=1  , i=2
                第2次循环:i<=5---》满足,执行:sum=3   ,i=3
                第3次循环:i<=5---》满足,执行:sum=6  ,i=4
                第4次循环:i<=5---》满足,执行:sum=10 ,i=5
                第5次循环:i<=5---》满足,执行:sum=15 ,i=6
                第6次循环:i<=5---》不满足,循环停止。
                
                结论:循环只是减少了程序员的工作,而不是减少了计算机底层的工作。
                
                4.循环的组成:
                【1】条件初始化  【2】条件判断  【3】循环体   【4】迭代
                总结:初始化什么,就判断什么。判断什么就执行什么。执行什么就迭代什么。
                上面四步骤的执行过程:
                【1】【2】【3】【4】【2】【3】【4】【2】【3】【4】
                
                
                */
                
        }
}

【2】do-while:

public class TestDoWhile{
        public static void main(String[] args){
                //1+2+3+4+5
                
                
                int i=16;//条件初始化
                int sum=0;
                do{
                        sum=sum+i;//循环体
                        i++;//迭代
                }while(i<=5);//条件判断---->后面必须加上;,否则编译报错
                
                System.out.println(i);//17
                System.out.println(sum);//16
                
                /*
                int i=16;
                int sum=0;
                while(i<=5){
                        sum=sum+i;
                        i++;
                }	
                System.out.println(i);//16
                System.out.println("和是:"+sum);	//0
                */
                
                
                
                /*
                1.while和do-while的区别:
                        while :先判断,再执行。很可能一次都不执行。
                        do-while:先执行,再判断,无论如何都会被执行一次。
                
                2.在什么情况下只能用do-while呢?
                      考试  批卷   是否及格 
                          
                          while(是否及格 ){
                                  考试  批卷 
                          }
                          ----不合适
                          
                          
                          do{
                                  考试  批卷
                          }while(是否及格)
                      ----合适
                
                */
        }
}

【3】for

public class TestFor{
        public static void main(String[] args){
                //1+2+3+4+5:
                int sum=0;
                int i;
                for(i=16;i<=5;i++){
                        sum+=i;
                }
                System.out.println(i);
                System.out.println(sum);
                /*
                1.for格式:
                for([1]条件初始化;[2]条件判断;[3]迭代){
                        [4]循环体;
                }
                
                2.执行顺序:
                [1][2][4][3][2][4][3][2][4][3]
                
                3.利用for循环代码简单,所以以后相对比较常用。特别是:循环数量固定的情况。
                
                4.for循环  格式特别灵活  :但是你自己写代码 别太灵活了 怕你理解不了 
                
                5.for死循环:   
                for(;;){
                        //....
                }
                
                6.while,do-while,for谁的效率最高?一样的
                  谁的效率最高:高斯算法最高 。102*50=5050
                
                */
        }
}
public class TestFor02{
        public static void main(String[] args){
                //输出1-100中被3整除的数,每行输出5个:
                int count=0;//计数器:其实就是定义一个变量,自增操作
                for(int i=1;i<=100;i++){
                        if(i%3==0){//被3整除的数
                                System.out.print(i+"\t");
                                count++;
                                if(count%5==0){
                                        System.out.println();
                                }
                        }
                }
        }
}

break

public class TestFor03{
        public static void main(String[] args){
                //1-100求和,当和第一次大于405的时候,停止程序。
                int sum=0;
                for(int i=1;i<=100;i++){
                        sum+=i;
                        if(sum>405){
                                break;//结束(最近的)循环。
                        }
                        System.out.println(sum);
                }
                
        }
}

【2】break:深入理解:

public class TestFor04{
        public static void main(String[] args){
                
                //break:结束最近的循环
                /*
                for(int i=1;i<=100;i++){
                        if(i==33){
                                break;
                        }
                        System.out.println(i);
                }
                */
                
                for(int i=1;i<=100;i++){
                        while(i==33){
                                break;
                        }
                        System.out.println(i);
                }
                
        }
}

continue、return

【1】continue:

public class TestFor06{
        public static void main(String[] args){
                //输出1-100中被5整除的数:
                //方式1:
                /*for(int i=1;i<=100;i++){
                        if(i%5==0){
                                System.out.println(i);
                        }
                }*/
                //方式2:
                for(int i=1;i<=100;i++){
                        if(i%5!=0){
                                continue;//跳出当前循环,进行下一次循环。
                        }
                        System.out.println(i);
                }
                
        }
}

 【2】continue深入:

public class TestFor04{
        public static void main(String[] args){
                
                //continue:跳出当前循环,进行下一次循环:
                /*
                for(int i=1;i<=100;i++){
                        if(i==33){
                                continue;
                        }
                        System.out.println(i);
                }
                */
                
                for(int i=1;i<=100;i++){
                        while(i==33){
                                continue;
                        }
                        System.out.println(i);
                }
                
                
        }
}

【3】return:

public class TestFor04{
        public static void main(String[] args){
                
                
                
                for(int i=1;i<=100;i++){
                        if(i==33){
                                return;//结束当前的方法
                        }
                        System.out.println(i);
                }
                
                System.out.println("aaaaaq");
                
                
                
        }
}

【4】总结:
break:结束最近的循环
continue:跳出当前循环,进入下一次循环
return:结束当前方法

/*
实现一个功能: 【1】请录入10个整数,当输入的数是666的时候,退出程序。
               【2】判断其中录入正数的个数并输出。
               【3】判断系统的退出状态:是正常退出还是被迫退出。
*/
import java.util.Scanner;
public class TestFor07{
        public static void main(String[] args){
                //请录入10个整数
                Scanner sc=new Scanner(System.in);
                //计数器:
                int count=0;
                boolean flag=true;//把它理解成一个“开关”,暂定true就是开关开着的。
                for(int i=1;i<=10;i++){
                        System.out.print("请录入第"+i+"个数:");
                        int num=sc.nextInt();
                        //判断其中录入正数的个数
                        if(num>0){
                                count++;
                        }
                        
                        //当输入的数是666的时候,退出程序。
                        if(num==666){
                                flag=false;
                                break;
                        }
                        
                }
                
                System.out.println("正数的个数是:"+count);
                
                if(flag){
                        System.out.println("正常退出");
                }else{
                        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
*/
public class TestFor08{
        public static void main(String[] args){
                //1*6=6   2*6=12  3*6=18  4*6=24  5*6=30  6*6=36
                /*
                System.out.print("1*6=6"+"\t");
                System.out.print("2*6=12"+"\t");
                System.out.print("3*6=18"+"\t");
                System.out.print("4*6=24"+"\t");
                System.out.print("5*6=30"+"\t");
                System.out.print("6*6=36"+"\t");
                */
                /*
                for(int i=1;i<=6;i++){
                        System.out.print(i+"*6="+i*6+"\t");
                }
                //换行:
                System.out.println();
                
                
                //1*7=7   2*7=14  3*7=21  4*7=28  5*7=35  6*7=42  7*7=49
                for(int i=1;i<=7;i++){
                        System.out.print(i+"*7="+i*7+"\t");
                }
                //换行:
                System.out.println();
                
                
                //1*8=8   2*8=16  3*8=24  4*8=32  5*8=40  6*8=48  7*8=56  8*8=64
                for(int i=1;i<=8;i++){
                        System.out.print(i+"*8="+i*8+"\t");
                }
                //换行:
                System.out.println();
                */
                
                for(int j=1;j<=9;j++){
                        for(int i=1;i<=j;i++){
                                System.out.print(i+"*"+j+"="+i*j+"\t");
                        }
                        //换行:
                        System.out.println();
                }
        }
}
/*
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*8=8   2*8=16  3*8=24  4*8=32  5*8=40  6*8=48  7*8=56  8*8=64
1*7=7   2*7=14  3*7=21  4*7=28  5*7=35  6*7=42  7*7=49
1*6=6   2*6=12  3*6=18  4*6=24  5*6=30  6*6=36
1*5=5   2*5=10  3*5=15  4*5=20  5*5=25
1*4=4   2*4=8   3*4=12  4*4=16
1*3=3   2*3=6   3*3=9
1*2=2   2*2=4
1*1=1
*/
public class TestFor09{
        public static void main(String[] args){
                for(int j=9;j>=1;j--){
                        for(int i=1;i<=j;i++){
                                System.out.print(i+"*"+j+"="+i*j+"\t");
                        }
                        //换行:
                        System.out.println();
                }
                
        }
}

打印各种形状

【1】矩形:

public class TestFor10{
        public static void main(String[] args){
                /*
                打印各种形状:
                **********
                **********
                **********
                **********
                */
                
                for(int j=1;j<=4;j++){//j:控制行数
                        //**********
                        for(int i=1;i<=10;i++){//i:控制每行的*的个数
                                System.out.print("*");
                        }
                        //换行:
                        System.out.println();//换行
                }
        }
}

【2】平行四边形:

public class TestFor10{
        public static void main(String[] args){
                /*
                打印各种形状:
                     **********
                    **********
                   **********
                  **********
                */
                
                for(int j=1;j<=4;j++){//j:控制行数
                        //加入空格:
                        for(int i=1;i<=(6-j);i++){
                                System.out.print(" ");
                        }
                
                
                        //**********
                        for(int i=1;i<=10;i++){//i:控制每行的*的个数
                                System.out.print("*");
                        }
                        //换行:
                        System.out.println();//换行
                }
        }
}

【3】三角形:

public class TestFor10{
        public static void main(String[] args){
                /*
                打印各种形状:
                     *
                    ***
                   *****
                  *******
                */
                
                for(int j=1;j<=4;j++){//j:控制行数
                        //加入空格:
                        for(int i=1;i<=(6-j);i++){//i:每行的空格数
                                System.out.print(" ");
                        }
                
                
                        //**********
                        for(int i=1;i<=(2*j-1);i++){//i:控制每行的*的个数
                                System.out.print("*");
                        }
                        //换行:
                        System.out.println();//换行
                }
        }
}

【4】菱形:

public class TestFor10{
        public static void main(String[] args){
                /*
                打印各种形状:
                     *
                    ***
                   *****
                  *******
                   *****
                    ***
                     *
                */
                //上面的三角形
                for(int j=1;j<=4;j++){//j:控制行数
                        //加入空格:
                        for(int i=1;i<=(6-j);i++){//i:每行的空格数
                                System.out.print(" ");
                        }
                
                
                        //**********
                        for(int i=1;i<=(2*j-1);i++){//i:控制每行的*的个数
                                System.out.print("*");
                        }
                        //换行:
                        System.out.println();//换行
                }
                //下面的三角形
                for(int j=1;j<=3;j++){//j:控制行数
                        //加入空格:
                        for(int i=1;i<=(j+2);i++){//i:每行的空格数
                                System.out.print(" ");
                        }
                
                
                        //**********
                        for(int i=1;i<=(7-2*j);i++){//i:控制每行的*的个数
                                System.out.print("*");
                        }
                        //换行:
                        System.out.println();//换行
                }
        }
}

【5】空心菱形:

public class TestFor10{
        public static void main(String[] args){
                /*
                打印各种形状:
                     *
                    * *
                   *   *
                  *     *
                   *   *
                    * *
                     *
                */
                //上面的三角形
                for(int j=1;j<=4;j++){//j:控制行数
                        //加入空格:
                        for(int i=1;i<=(6-j);i++){//i:每行的空格数
                                System.out.print(" ");
                        }
                
                
                        //**********
                        for(int i=1;i<=(2*j-1);i++){//i:控制每行的*的个数
                                if(i==1||i==(2*j-1)){
                                        System.out.print("*");
                                }else{
                                        System.out.print(" ");
                                }
                        }
                        //换行:
                        System.out.println();//换行
                }
                //下面的三角形
                for(int j=1;j<=3;j++){//j:控制行数
                        //加入空格:
                        for(int i=1;i<=(j+2);i++){//i:每行的空格数
                                System.out.print(" ");
                        }
                
                
                        //**********
                        for(int i=1;i<=(7-2*j);i++){//i:控制每行的*的个数
                                if(i==1||i==(7-2*j)){
                                        System.out.print("*");
                                }else{
                                        System.out.print(" ");
                                }
                        }
                        //换行:
                        System.out.println();//换行
                }
        }
}
public class TestFor11{
        public static void main(String[] args){
                //正方形的宽
                int size=19;//必须是奇数
                //中轴线所在的列:
                int centerNum=size/2+1;
                int startNum=centerNum;
                int endNum=centerNum;
                
                //定义一个开关:
                boolean flag=true;
                for(int j=1;j<=size;j++){
                        for(int i=1;i<=size;i++){
                                //if(i>=startNum&&i<=endNum){
                                if(i==startNum||i==endNum){
                                        System.out.print("*");
                                }else{
                                        System.out.print(" ");
                                }
                        }
                        
                        if(endNum==size){
                                flag=false;
                        }
                        
                        //边界要变化:
                        if(flag){
                                startNum--;
                                endNum++;
                        }else{
                                startNum++;
                                endNum--;
                        }
                        System.out.println();
                }
        }
}

三重循环

【2】发现一件事:
发现在双重执行结束的时候,外层循环的变量和里层循环的变量的 匹配情况是:
一定会匹配一次,挨个匹配。

比如:
刚才代码中a有五种可能性,b有三种可能性,会将所有的可能性匹配一次:

 【3】百钱买百鸡:

/*
百钱买百鸡:
公鸡5文钱一只,母鸡3文钱一只,小鸡3只一文钱,
用100文钱买一百只鸡,其中公鸡,母鸡,小鸡都必须要有,问公鸡,母鸡,小鸡要买多少只刚好凑足100文钱。
三元一次方程组:
公鸡:x只
母鸡:y只
小鸡:z只
x+y+z=100
5x+3y+z/3=100
*/
public class TestFor13{
        public static void main(String[] args){
                /*
                for(int x=1;x<=19;x++){
                        for(int y=1;y<=31;y++){
                                for(int z=1;z<=100;z++){
                                        if((x+y+z==100)&&(5*x+3*y+z/3==100)&&(z%3==0)){
                                                System.out.println(x+"\t"+y+"\t"+z);
                                        }
                                }
                        }
                }
                */
                for(int x=1;x<=19;x++){
                        for(int y=1;y<=31;y++){
                                int z=100-x-y;
                                if((x+y+z==100)&&(5*x+3*y+z/3==100)&&(z%3==0)){
                                        System.out.println(x+"\t"+y+"\t"+z);
                                }
                        }
                }
        }
}

5、方法

【1】什么是方法
封装在一起来执行操作语句的集合,用来完成某个功能操作
在某些语言中称为函数或者过程

【2】定义方法
[修饰符]  方法返回值类型  方法名(形参列表 ) {
     方法体
     return 返回值;       
}
例如:
public static  int add(int a, int b, int c) {
     int k = a + b + c;
     return k;
}
修饰符:封装性时再讲,决定了方法的工作范围
返回值类型:必选,如果没有返回值,须写void。方法只能返回一个值
方法名:见名知意等
参数列表:可以0个、1个、多个,需要同时说明类型。称为形式参数
方法体:完成具体功能。如果有返回值,必须有return语句;如果没有返回值,默认最后一条语句是return,可以省略
【3】方法的调用

【4】方法的重载
一个类中可以定义有相同的名字,但参数不同的多个方法。

调用时,会根据不同的参数表选择对应的方法。

判断依据:同一个类+同一个方法名

不同:参数列表不同(类型,个数,顺序不同)

注意:
只有返回值不同不构成方法的重载
        int     a(String str){},
        void  a{String i}, 
        调用:a(),        谁能告诉我是调哪个方法?
只有形参的名称不同,不构成方法的重载


方法的定义、调用

【1】什么是方法
封装在一起来执行操作语句的集合,用来完成某个功能操作
在某些语言中称为函数或者过程
之前接触过:特殊的方法main,程序执行的入口
public static void main(String  [ ] args){
                                实现功能的语句
}
不可能所有的功能都放到main中,需要定义其他方法完成指定功能,需时要调用方法即可
【2】定义方法
[修饰符]   方法返回值类型   方法名(形参列表 ) {
                                方法体
                                return 返回值;       
}
public static  int add(int a, int b, int c) {
                                int k = a + b + c;
                                return k;
}
修饰符:封装性时再讲,决定了方法的工作范围
返回值类型:必选,如果没有返回值,须写void。方法只能返回一个值
方法名:
参数列表:可以0个、1个、多个,需要同时说明类型。称为形式参数
方法体:完成具体功能。
                                                        如果有返回值,必须有return语句;
                                                        如果没有返回值,默认最后一条语句是return,可以省略。

 【3】代码练习:

public class TestMethod01{
        /*
        1.方法:对特定的功能,进行一个提取,进行一个封装,将这个功能代码包装起来,以后方便其他人使用。
           这个过程就叫对代码的抽取--》方法的定义:
        2.方法定义的格式:
        [修饰符] 返回值类型 方法名(形式参数列表){
                方法体;
                return+方法的返回值;
        }
        PS:发现以前我们程序的入口其实就是一个方法,方法的名字是main,叫main方法。
            那么我们要是定义方法的话,就是跟main方法平级的概念。
        
        3.方法定义好之后,是需要在别处调用的。
        4.详细说一下定义的格式都是什么意思:
        (1)修饰符:public static -----》暂时不予讲解,留到面向对象一章学习,暂时会用即可。
        (2)返回值类型:你调用这个方法,会给你返回一个结果,这个结果对应的类型
            可能是什么类型:a.基本数据类型 (byte,short,int,long,float,double,char,boolean) 
               		    b.引用数据类型
        (3)方法名:见名之意 ,首字母小写,其余遵循驼峰命名  :addNum,add,,,,
        (4)形式参数(形参): 方法定义的时候,用来接收你传过来的参数---》num1,num2
             实际参数:方法调用的时候,具体传过去的参数 ----->10,20
             PS:形参个数不固定,类型不固定,顺序不固定
        (5)方法体;  执行你这个功能的具体的代码	,业务逻辑代码
    (6)return+方法的返回值;——---》return后面的返回值返回到了方法的调用处
             有没有一种可能,这个方法没有返回值?可能
                 当方法没有返回值的时候,return;可以省略不写,并且对应的返回值类型为:void
                 
        (7)什么时候有返回值,什么时候没有返回值啊?看心情。
             自己考虑,当这个返回值在接下来的代码中有用的时候,就带返回值。
                 假如这个方法的返回值以后也没啥用了,就不用写了。
        (8)方法定义的时候,明确两件事:
             a.这个方法中的不确定因素要作为形参
                 b.明确这个方法时候有返回值
        (9)方法调用的时候,负责两件事:
             a.负责把形参具体的数据传过去---》传入实参
                 b.负责考虑是否接收返回值
                 
        5.定义方法的好处:
        增加代码的复用性
        增加代码的可读性
        */
        //定义的这个方法:计算两个数之和:
        public static int add(int num1,int num2){
                int sum=0;
                sum+=num1;
                sum+=num2;
                return sum;
        }
        
        public static void addNum(double num1,double num2){
                System.out.println("两个数的和是:"+(num1+num2));
                //return ;
        }
        
        
        public static void main(String[] args){
                addNum(9.8,6.9);
                
                
                //求10+20:
                //方法的调用:
                int a=add(10,20);
                System.out.println("和为:"+a);
                
                System.out.println(a+100);
                
                
                /*
                int num1=10;
                int num2=20;
                int sum=0;
                sum+=num1;
                sum+=num2;
                System.out.println("和为:"+sum);
                */
                
                //求30+50:
                System.out.println(add(30,50));
                /*
                int num3=30;
                int num4=50;
                int sum1=0;
                sum1+=num3;
                sum1+=num4;
                System.out.println("和为:"+sum1);
                */
                
                //求90+50:
        }
}

【4】练习:

//功能:定义一个方法:猜我心中的数,看你是否能猜对。
import java.util.*;
public class TestMethod02{
        public static void main(String[] args){
                //键盘录入你猜的数:
                Scanner sc=new Scanner(System.in);
                System.out.print("请录入你猜的数:");
                int guess=sc.nextInt();
                boolean flag=guessNum(guess);
                if(flag){
                        System.out.println("猜对了!");
                }else{
                        System.out.println("猜错了!");
                }
        }
        
        
        /*
        定义一个方法:
        明确:
        (1)不确定因素
        (2)是否有返回值
        
        
        */
        public static boolean guessNum(int num){
                //给出我心中的一个数:
                int heartNum=(int)(Math.random()*6)+1;
                
                //判断:
                if(heartNum==num){
                        return true;
                }else{
                        return false;
                }
        }
        
        
        
}

方法的重载

【1】方法重载
一个类中可以定义有相同的名字,但参数不同的多个方法
调用时,会根据不同的参数表选择对应的方法。
【2】判断依据
同一个类
同一个方法名
不同:参数列表不同(类型,个数,顺序不同)

PS:注意
只有返回值不同不构成方法的重载(
        int     a(String str){},
        void  a(String i){}, 
        调用:a(),        谁能告诉我是调哪个方法?
只有形参的名称不同,不构成方法的重载
【3】代码:

public class TestMethod04{
        public static void main(String[] args){
                //调用方法:
                //10+20:
                System.out.println(add(10,20));
                //10+20+30:
                //System.out.println(add(add(10,20),30));
                System.out.println(add(10,20,30));
                //20+40+60+80:
                //System.out.println(add(add(20,40),add(60,80)));
                //9.8+6.5:
                //System.out.println(add(9.8,6.5));
                System.out.println(add(9.8,6.5));
        }
        
        //定义方法:求和:
        public static int add(int num1,int num2){
                return num1+num2;
        }
        //3.下面这个方法和上面的add方法,是方法的重复定义,不是重载,形参名字叫什么无所谓
        public static int add(int a,int b){
                return a+b;
        }
        public static int add(int num1,int num2,int num3){
                return num1+num2+num3;
        }
        public static double add(double num1,double num2){
                return num1+num2;
        }
        public static double add(int num1,double num2){
                return num1+num2;
        }
        public static double add(double num1,int num2){
                return num1+num2;
        }
        
        /*
        1.方法的重载:
          当不同的方法完成的功能相似,定义为方法名相同,形参列表不同,构成了方法的重载。
        2.重载的条件:
          (0)在同一个类中 (1)方法名相同 (2)形参列表不同 (个数不同,类型不同,顺序不同)
          -----意味着方法的重载跟修饰符,返回值类型无关
        3.
        
        
        */
        
}

【4】下面的代码尝试即可:

public class TestMethod05{
        public static void main(String[] args){
                a(10);
        }
        public static void a(double num1){
                System.out.println("44444");
        }
        /*
        public static void a(long num1){
                System.out.println("22222");
        }
        
        public static void a(int num1){
                System.out.println("111111");
        }
        */
        
        public static void a(float num1){
                System.out.println("33333");
        }
        
        
        
        
}

递归

什么是递归(recursion)
程序调用自身的编程技巧称为递归。
一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法

 

 

求阶乘,斐波那契数列 

 【2】求阶乘:

public class Test01{
        public static void main(String[] args){
                //计算:6*5*4*3*2*1=6!  6的阶乘:
                //方式1:--->循环
                int result=1;
                for(int i=6;i>=1;i--){
                        result*=i;
                }
                System.out.println("阶乘为:"+result);
                
                //方式2:
                System.out.println(fac(6));
                
        }
        public static int fac(int n){
                if(n==1){//结束条件
                        return 1;
                }
                return n*fac(n-1);//递归体:自己调用自己
        }
        
        
        /*
        fac(6)
        --->return 6*fac(5)
        --->return 6*5*fac(4)
        --->return 6*5*4*fac(3)
        --->....
        --->return 6*5*4*3*2*fac(1)
        fac(1)--->return 1:
        return 6*5*4*3*2*1
        
        
        
        
        */
        
        
}


递归:自己调用自己

递归两个条件:1.递归体  2.结束条件  

递归优点:代码简单

缺点:时间空间消耗大(时空消耗)
     
      不好理解

【3】斐波那契数列:

/*
在控制台上输出斐波那契数列:
斐波那契数列指的是这样一个数列:
 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368
特别指出:第1项是0,第2项是第一个1。
*/
public class Test02{
        public static void main(String[] args){
                //方式1:循环:
                int num1=0;
                int num2=1;
                int numn=1;
                /*
                //求第3项:
                numn=num1+num2;
                num1=num2;
                num2=numn;
                
                //求第4项:
                numn=num1+num2;
                num1=num2;
                num2=numn;
                
                //求第5项:
                numn=num1+num2;
                num1=num2;
                num2=numn;
                */
                long startTime=System.currentTimeMillis();
                int n=44;//第几项
                for(int i=3;i<=n;i++){
                        numn=num1+num2;
                        num1=num2;
                        num2=numn;
                        
                }
                System.out.println(numn);
                long endTime=System.currentTimeMillis();
                System.out.println("循环执行的时间:"+(endTime-startTime));
                
                //方式2:递归:
                long startTime2=System.currentTimeMillis();
                System.out.println(fibo(n));
                long endTime2=System.currentTimeMillis();
                System.out.println("递归执行的时间:"+(endTime2-startTime2));
        }
        
        //定义一个方法,帮我求第n项的数:
        public static int fibo(int n){
                if(n==1){
                        return 0;
                }
                if(n==2){
                        return 1;
                }
                return fibo(n-1)+fibo(n-2);
        }
        
}

6、数组

引入

import java.util.*;
public class TestFor20{
        public static void main(String[] args){
                //功能:录入十个学生的成绩,求和,求平均数:
                //录入十个学生的成绩
                //定义一个变量sum接收和:
                int sum=0;
                Scanner sc=new Scanner(System.in);
                for(int i=1;i<=10;i++){
                        System.out.print("请录入第"+i+"个学生的成绩:");
                        int score=sc.nextInt();
                        //求和
                        sum+=score;
                }
                System.out.println("和为:"+sum);
                
                //求平均数
                System.out.println("平均数为:"+sum/10);
                
                
        }
}

【2】上面的代码中有什么缺点?
例如:求出第6个学生的成绩是多少?  这个不可能完成,因为for循环每次结束,score就要消失了,
所以学生的成绩并没有存储下来。
我们要做的事就是:将学生的成绩存储下来。--------利用数组

数组的学习

【1】数组是相同类型数据的有序集合.
相同类型的若干个数据,按照一定先后次序排列组合而成。
其中,每一个数据称作一个数组元素
每个数组元素可以通过一个下标来访问它们.

【2】数组特点:
其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
其元素必须是相同类型,不允许出现混合类型。
数组中的元素可以是任何数据类型,包括基本类型和引用类型。
长度:通过属性获取:length
下标从0开始,到数组.length-1结束。


【3】代码:

public class TestArray01{
        public static void main(String[] args){
                //数组的学习:1.声明  2.创建  3.赋值  4.使用
                //数组作用:用于数据的存储,数据有很多种类型,存什么类型的数据呢?
                //数组有个特点:一旦定义一个数组,其中只能存放一种数据类型。
                //以int类型数组为案例讲解:
                
                //1.声明
                int[] arr;//定义一个数组,int类型数组,名字叫做arr
                int arr2[];
                //假如你只声明了数组,没有赋值,那么其实这个变量相当于不存在,反编译看根本没有这些变量。
                int[] arr3=null;//声明不赋值 和  =null  ,不是一回事,=null是真实存在这个数组的,
                //2.创建
                arr=new int[4];
                
                //PS:声明和创建可以用一句话表示:int[] arr=new int[4];
                
                
                
                //3.赋值
                arr[0]=17;
                arr[1]=90;
                arr[2]=40;
                arr[3]=71;
                //arr[4]=100;
                //数组越界异常:Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
                
                //在数组开辟空间以后,每个位置都是有下标/索引的,我们就是通过这个索引来访问元素的。
                //下标从0开始,到数组长度-1(arr.length-1)结束,访问其他位置就出异常。
                
                //4.使用
                System.out.println(arr[2]);
                System.out.println(arr[2]+100);//可以参与到后面的运算中去了。。。
                
                System.out.println("数组的长度:"+arr.length);
                
        }
}

数组声明创建三种方式

1.静态初始化
int[] arr={12,324,45,56,67};
int[] arr=new int[]{12,324,45,56,67};

2.动态初始化
int[] arr=new int[4];
arr[0]=12;
arr[1]=213;
arr[2]=34;

【1】代码:

import java.util.*;
public class TestFor20{
        public static void main(String[] args){
                //功能:录入十个学生的成绩,求和,求平均数:
                //录入十个学生的成绩
                //定义一个变量sum接收和:
                int sum=0;
                Scanner sc=new Scanner(System.in);
                
                //定义一个数组,int类型的数组,长度为:10:
                int[] scores=new int[10];
                
                
                for(int i=1;i<=10;i++){
                        System.out.print("请录入第"+i+"个学生的成绩:");
                        int score=sc.nextInt();
                        //将每个成绩存入数组中:
                        scores[i-1]=score;
                        //求和
                        sum+=score;
                }
                System.out.println("和为:"+sum);
                
                //求平均数
                System.out.println("平均数为:"+sum/10);
                
                
                //求出第6个学生的成绩是多少?
                
                System.out.println(scores[5]);
                
                //对数组进行遍历查看:(查看数组中的每一个元素:)
                
                //方式1:普通for循环
                System.out.println("--------普通for循环----------------");
                for(int i=0;i<=scores.length-1;i++){
                        System.out.println("第"+(i+1)+"个学生的成绩是:");
                        System.out.println(scores[i]);
                }
                
                //方式2:增强for循环(foreach循环)
                System.out.println("--------增强for循环----------------");
                for(int s:scores)//对scores数组进行遍历,每一次的结果都用int s这个变量接收
                        System.out.println(s);//循环的每一次将s在控制台上打印出来。
                
                
                
                //增强for循环:优点:代码简单    缺点:不能进行跟索引相关的操作。
                
                //方式3:逆向遍历:
                System.out.println("--------逆向遍历----------------");
                for(int i=scores.length-1;i>=0;i--)
                        System.out.println(scores[i]);
                
                
        }
}

数组的应用

数组的最值问题

【1】实现一个功能,求出数组中最大的数,和最大数对应的索引。(不是排序)
----思路:“打擂”原理。

public class TestArray02{
        public static void main(String[] args){
                //实现一个功能,求出数组中最大的数,和最大数对应的索引。
                //给定一个数组:
                int[] arr={12,23,45,7,27,21,57,3};
                //"打擂"
                //暂定数组最大数:
                int maxNum=12;
                //暂定数组最大数对应的索引:
                int maxIndex=0;
                //“挨个上去打”:--一个一个来---》数组进行遍历:
                for(int i=0;i<=arr.length-1;i++){
                        if(arr[i]>=maxNum){
                                maxNum=arr[i];
                                maxIndex=i;
                        }
                }
                
                System.out.println("当前数组中最大的数:"+maxNum);
                System.out.println("当前数组中最大数的索引:"+maxIndex);
                
                
        }
}

【2】将最值问题提取出一个方法:
定义一个方法,求数组中最大值:

public class TestArray03{
        public static void main(String[] args){
                //实现一个功能,求出数组中最大的数
                //给定一个数组:
                int[] arr={12,23,45,7,127,21,57,3};
                int maxNum=getMaxNum(arr);
                System.out.println(maxNum);
        }
        
        //定义一个方法:求最大值:
        public static int getMaxNum(int[] arr){
                //"打擂"
                //暂定数组最大数:
                int maxNum=12;
                
                //“挨个上去打”:--一个一个来---》数组进行遍历:
                for(int i=0;i<=arr.length-1;i++){
                        if(arr[i]>=maxNum){
                                maxNum=arr[i];
                        }
                }
                
                return maxNum;
        }
}


总结:
0.形参和局部变量都放入栈中,new出来的东西放入堆中
1.引用数据类型做形参,内存:传入的是 地址值的“副本”
2.以前的基本数据类型:直接就是值传递
3.当方法结束的时候,方法对应开辟的栈帧要在栈中消失,---》出栈
4.堆中无用内存被垃圾收集机制清理掉


查询

【1】查询指定位置的元素:

public class TestArray04{
        public static void main(String[] args){
                //给定一个数组,查询下标为3的元素:
                int[] arr={12,34,45,576,3,5};
                //查询下标为3的元素
                System.out.println(arr[3]);
                //查询下标为0的元素
                System.out.println(arr[0]);//会根据地址进行查找,一步到位!
        }
}

数组的优点:查找效率高,一步到位!

public class TestArray04{
        public static void main(String[] args){
                //给定一个数组,查询下标为3的元素:
                int[] arr={12,34,45,576,3,5};
                //查询下标为3的元素
                System.out.println(arr[3]);
                //查询下标为0的元素
                System.out.println(arr[0]);//会根据地址进行查找,一步到位!
                
                //给定一个数组,查询第一个36这个元素对应的索引:
                int[] arr2={12,36,23,45,67,36,8};
                
                //遍历数组,挨个跟36比较,如果匹配 就停止查找
                int index=-1;//给除了0-arr2.length-1之间的值都可以,一般我们都给-1
                for(int i=0;i<=arr2.length-1;i++){
                        if(arr2[i]==36){
                                index=i;
                                break;//找到第一个36循环就停止!
                        }
                }
                
                if(index>=0){
                        System.out.println("第一个36对应的索引是:"+index);
                }else{
                        System.out.println("查无此数!");
                }
                
        }
}

【3】查询指定元素对应的索引:---》提取一个方法:

public class TestArray05{
        public static void main(String[] args){
                //给定一个数组,查询第一个36这个元素对应的索引:
                int[] arr2={12,36,23,45,67,36,8};
                
                //调用下面的方法:
                int index=getIndex(arr2,136);
                
                //对返回值进行判断:
                if(index>=0){
                        System.out.println("第一个36对应的索引是:"+index);
                }else{
                        System.out.println("查无此数!");
                }
                
        }
        
        public static int getIndex(int[] arr,int num){
                //遍历数组,挨个跟36比较,如果匹配 就停止查找
                int index=-1;//给除了0-arr2.length-1之间的值都可以,一般我们都给-1
                for(int i=0;i<=arr.length-1;i++){
                        if(arr[i]==num){
                                index=i;
                                break;//找到第一个36循环就停止!
                        }
                }
                //方法返回值:index:
                return index;
        }
        
        
}

添加元素

public class TestArray06{
        public static void main(String[] args){
                //给定一个数组,在下标为1的位置上添加一个元素888
                //{12,34,45,65,45,44,7}--->{12,888,34,45,65,45,44}
                //给定数组:
                int[] arr={12,34,45,65,45,44,7};
                //          0  1  2  3  4  5  6
                
                //输出添加前的数组:
                for(int a:arr){
                        System.out.print(a+"\t");
                }
                
                //添加:
                /*
                arr[6]=arr[5];
                arr[5]=arr[4];
                arr[4]=arr[3];
                arr[3]=arr[2];
            arr[2]=arr[1];
                */
                int n=3;//在下标为n的位置上添加元素
                for(int i=arr.length-1;i>=(n+1);i--){
                        arr[i]=arr[i-1];
                }
                arr[n]=666;		
                
                
                //输出添加后的数组:
                System.out.println("\n---添加后:---");
                for(int a:arr){
                        System.out.print(a+"\t");
                }
                
                
        }
}

删除元素

【1】删除指定位置的元素:

public class TestArray07{
        public static void main(String[] args){
                //给定一个数组,删除下标为2的元素:
                //{12,34,45,65,45,44,7}--->{12,34,65,45,44,7,0}
                //给定数组:
        int[] arr={12,34,45,65,45,44,7};
                //          0  1  2  3  4  5  6
                
                //遍历删除前的数组:
                for(int a:arr){
                        System.out.print(a+"\t");
                }
                
                //删除下标为2的元素:
                /*
                arr[2]=arr[3];
                arr[3]=arr[4];
                arr[4]=arr[5];
            arr[5]=arr[6];
                */
                int index=2;//我想要删除下标为index的元素
                for(int i=index;i<=arr.length-2;i++){
                        arr[i]=arr[i+1];
                }
                arr[arr.length-1]=0;
                
                //遍历删除后的数组:
                System.out.println("\n-----删除后-----:");
                for(int a:arr){
                        System.out.print(a+"\t");
                }
        }
}

【2】删除指定的元素:

public class TestArray08{
        public static void main(String[] args){
                //给定一个数组,删除数组中的元素34(第一个):
                //{12,34,45,65,45,44,7}--->{12,45,65,45,44,7,0}
                //给定数组:
        int[] arr={12,34,45,65,45,44,7};
                //          0  1  2  3  4  5  6
                
                //遍历删除前的数组:
                for(int a:arr){
                        System.out.print(a+"\t");
                }
                //找到134这个元素对应的索引:
                int index=-1;
                for(int i=0;i<=arr.length-1;i++){
                        if(arr[i]==134){
                                index=i;
                                break;
                        }
                }
                if(index>=0){
                        //删除下标为2的元素:
                
                        //我想要删除下标为index的元素---》利用上面的index:
                        for(int i=index;i<=arr.length-2;i++){
                                arr[i]=arr[i+1];
                        }
                        arr[arr.length-1]=0;
                }else{
                        System.out.println("\n并没有找到你要删除的那个元素!");
                }
                
                //遍历删除后的数组:
                System.out.println("\n-----删除后-----:");
                for(int a:arr){
                        System.out.print(a+"\t");
                }
        }
}

总结:
数组的优点:查询效率高,一步到位
数组的缺点:删除和添加效率低,需要移动大量的元素

main方法讲解

【1】main方法,程序的入口,有固定的格式:
public static void main(String[] args){

}
分析:
public static --->方法的权限修饰符(面向对象)
void:没有方法的返回值,类型对应为void
main:方法名
(String[] args):形式参数---》方法定义的不确定因素
【2】程序中是否可以有其他的方法,名字为main?可以:

public class Testmain{
        //程序的入口,格式固定:
        public static void main(String[] args){
                
        }
        //重载:同一个类中,只跟方法名和形参列表有关
        public void main(){
                
        }
}

【3】对于main方法来说,形参是String[] args,那么虚拟机在调用main方法的时候,是否传入参数?可以,在默认的情况下,实参为new String[0]:

public class Testmain{
        //程序的入口,格式固定:
        public static void main(String[] args){//String[] args=new String[0];
                //int[] arr1;--->反编译发现arr1不存在
                //int[] arr2=null;
                //System.out.println(arr2.length);--->会报错,空指针异常
                //int[] arr3=new int[0];
                //System.out.println(arr3.length);//0	
                
                System.out.println(args.length);
                for(String s:args){
                        System.out.println(s);
                }
        }
        //重载:同一个类中,只跟方法名和形参列表有关
        public void main(){
                
        }
}

可变参数 

public class TestArray10{
        public static void main(String[] args){
                //add();
                //add(10);
                //add(10,20);
                //add(10,20,30);
                add(10,20,30,40);
                //add(new int[]{12,34,45,6});
        }
        /*
        1.int...arr:可变参数,在JDK1.5之后新出的
        2.作用:它可以帮我们解决方法名相同,形参列表不同的重载问题
        3.表面上我们在使用可变参数,但是实际上 内部当做数组来处理。
        4.当可变参数和其他类型一起作为形参的时候,可变参数必须放在最后。
        
        */
        public static void add(int a,int...arr){
                System.out.println("你好。。");
                //处理arr:
                for(int num:arr){
                        System.out.println(num);
                }
                System.out.println("--------------------");
        }
        
        
}

Arrays工具类

【1】Arrays工具类中常用方法:

import java.util.*;
public class TestArray11{
        public static void main(String[] args){
                //操纵数组,先给定一个数组:
                int[] arr=new int[]{136,6,27,18,78};
                //Arrays工具类---:
                //1.toString 
                //System.out.println(Arrays.toString(arr));//数组的遍历,并且以一个好看的形式打印在控制台。
                //自己实现:[12, 34, 56, 67, 78]
                /*
                System.out.print("[");
                for(int i=0;i<=arr.length-1;i++){
                        if(i!=arr.length-1){
                                System.out.print(arr[i]+",");
                        }else{
                                System.out.print(arr[i]+"]");
                        }
                }
                */
                //2.排序:
                //Arrays.sort(arr);//按照升序排序
                //System.out.println(Arrays.toString(arr));
                
                //3.二分法查找:必须在有序的数组中进行查找,如果查找不到返回值为负数!
                //Arrays.sort(arr);
                //System.out.println(Arrays.binarySearch(arr,189));//在arr数组中找18元素对应的索引
                
                //4.复制:
                int[] newArr=Arrays.copyOf(arr,10);
                System.out.println(Arrays.toString(newArr));
                
                int[] newArr02=Arrays.copyOfRange(arr,2,4);//[2,4)--->2,3,没有4
                System.out.println(Arrays.toString(newArr02));
                
                //5.比较:
                int[] arr1={1,2,3,4};
                int[] arr2={1,2,3,4};
                System.out.println(arr1==arr2);//永远是:false---:》比较的是左右两侧的地址的值
                System.out.println(Arrays.equals(arr1,arr2));//比较的:数组中元素具体的数值。
                
                //6.填充:
                Arrays.fill(arr1,0);
                Arrays.fill(arr1,0,2,77);//[0,2)
                System.out.println(Arrays.toString(arr1));
        }
}

【2】System类中的数组复制方法:

 二维数组

public class TestArray12{
        public static void main(String[] args){
                //定义一个int[][]数组,二维数组:
                //数组的声明:
                int[] arr2[];
                int arr3[][];
                int[][] arr;
                //赋值:
                arr=new int[3][];//声明了一个数组arr,一维数组长度为3,
                arr=new int[3][4];//声明了一个数组arr,一维数组长度为3,每个格子中装的数组长度为4
                //arr={{1,23,435},{23,45,56,12},{34,56}};//声明了一个数组arr,一维数组长度为3,
                
                //声明和赋值可以合成为一句话:
                int[][] arr4=new int[3][];
                //开始向每个格子中放数组了:
                int[] a={1,2,3};
                arr4[0]=a;
                int[] b=new int[]{4,5,6};
                arr4[1]=b;
                arr4[2]=new int[]{7,8,9,10,11};
                
                
                //遍历二维数组:
                System.out.println(arr4[1][1]);
                System.out.println("--------");
                
                //普通for+普通for、
                for(int i=0;i<=arr4.length-1;i++){
                        for(int j=0;j<=arr4[i].length-1;j++){
                                System.out.println(arr4[i][j]);
                        }
                        System.out.println("--------");
                        
                }
                System.out.println("----普通for+增强for----");
                //普通for+增强for:
                for(int i=0;i<=arr4.length-1;i++){
                        for(int num:arr4[i]){
                                System.out.println(num);
                        }
                        System.out.println("--------");
                        
                }
                System.out.println("---增强for+增强for:-----");
                //增强for+增强for:
                for(int[] e:arr4){
                        for(int f:e){
                                System.out.println(f);
                        }
                }
                
                //增强for+普通for
                System.out.println("----增强for+普通for----");
                for(int[] e:arr4){
                        for(int i=0;i<=e.length-1;i++){
                                System.out.println(e[i]);
                        }
                }
                
                
        }
}

 基于数组的算法讲解

【1】算法的概念
       是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。
       以上是我在百度百科找到的解释,在我看来,算法就是求解一个问题所需要的步骤所形成的解决方法,每一步包括一个或者多个操作。无论是现实生活中还是计算机中,解决同一个问题的方法可能有很多种,在这N多种算法中,肯定存在一个执行效率最快的方法,那么这个方法就是最优算法。
       简单说:就是计算机解题的过程。
【2】算法的特性
算法具有五个基本特征:输入、输出、有穷性、确定性和可行性。
输入
0个输入是指算法本身定出了初始条件。
待解决的问题的输入。
输出
算法至少有一个输出。也就是说,算法一定要有输出。输出的形式可以是打印,也可以使返回一个值或者多个值等。也可以是显示某些提示。
有穷性
算法的执行步骤是有限的,算法的执行时间也是有限的。
确定性
算法的每个步骤都有确定的含义,不会出现二义性。
可行性
算法是可用的,也就是能够解决当前问题。

当然,回过头来一看,这五个特性都是废话,并且依稀记得大学老师都教过。所以,我们不用浪费脑力在这些不必要的概念上,因为大学早已离我远去,考试什么的跟我也没有一毛钱关系,只要知道这么回事就好。

【3】算法的设计要求
要设计一个好的算法,需要考虑以下4个特性(其实多半是废话)。
正确性
废话,谁会设计一个不能够解决问题的方法。
可读性
指算法无论是从设计思路上,还是从注释方面,都要能够保证算法是可读的,也就是可以被其他人员能够读懂的。其实也是废话,这是一个优秀的程序员必备的。
健壮性
通俗的讲,一个好的算法应该具有捕获异常/处理异常的能力。另外,对于测试人员的压力测试、边界值测试等刁难的测试手段,算法应该能够轻松的扛过去。
时间效率高和存储量低(时间和空间)
这其实是两个概念,时间效率就是指的时间复杂度,存储量就是指的空间复杂度。
翻译过来就是一个好的算法应该考虑时间复杂度和空间复杂度。而往往时间复杂度和空间复杂度是相互弥补的。也就是从某些角度,我们可以了通过牺牲算法运算时间的方式来减少对内存的占用,反之亦然。

下面我们就围绕这两个"复杂度"展开说明。在真正的开发中,时间复杂度尤为重要,空间复杂度我们不做太多说明。

【4】时间复杂度
       !!!切记:时间复杂度说的不是时间长短问题。因为不同的机器上同一个代码执行的时候都可能是不一样的,所以我们更关注的是一个算法中执行语句条数。
       时间频度:算法执行语句条数  
       但是我们一般都不去算语句到底执行多少次,我们一般用什么来衡量呢?:
       时间复杂度是:T(n)=O(n)  ----将时间复杂度用大O表示法表示   ????这是啥?
时间复杂度计算方法
1.用常数1取代运行时间中的所有加法常数。
2.在修改后的运行次数函数中,只保留最高阶项。
3.如果最高阶项存在且不是1,则去除与这个项相乘的常数。
最后,得到的最后结果就是时间复杂度。(取最高次幂)  
----???这又是啥???还是不懂,看例子就懂了:

 

 

 排序

冒泡排序

 

 【3】基础代码:

public class TestArray13{
        public static void main(String[] args){
                //给定一个数组:
                int[] arr={1,4,7,2,5,8};
                //排序:
                for(int j=1;j<=arr.length-1;j++){
                        for(int i=0;i<=arr.length-j-1;i++){
                                if(arr[i]>arr[i+1]){//前面的数比后面的数大,才进行交换:
                                        //交换
                                        int t;
                                        t=arr[i];
                                        arr[i]=arr[i+1];
                                        arr[i+1]=t;
                                }
                        }
                }
                //排序后输出:
                System.out.println(Arrays.toString(arr));
        }
}

【4】问一共进行了比较了多少次:

public class TestArray13{
        public static void main(String[] args){
                //给定一个数组:
                int[] arr={1,4,7,2,5,8};
                //定义一个计数器:用来计算比较了多少次:
                int count=0;
                //排序:
                for(int j=1;j<=arr.length-1;j++){
                        for(int i=0;i<=arr.length-j-1;i++){
                                count++;//只要进行比较,就加1操作。
                                if(arr[i]>arr[i+1]){//前面的数比后面的数大,才进行交换:
                                        //交换
                                        int t;
                                        t=arr[i];
                                        arr[i]=arr[i+1];
                                        arr[i+1]=t;
                                }
                        }
                }
                //排序后输出:
                System.out.println(Arrays.toString(arr));
                System.out.println("一共进行了"+count+"次比较");
        }
}

【5】问上面的代码缺点是啥?
(1)当数组是有序的时候,要进行很多无用的比较,所以当数组是有序的时候,就不用再进行下一趟比较了。
(2)变量应该放到循环之外,减少开空间的次数,提高效率
优化代码为:

public class TestArray13{
        public static void main(String[] args){
                //给定一个数组:
                int[] arr={1,2,3,4,5,6};
                //定义一个计数器:用来计算比较了多少次:
                int count=0;
                //排序:
                int t;
                boolean flag;
                for(int j=1;j<=arr.length-1;j++){
                        //每一趟比较,都拿一个开关,定义一个开关:
                        flag=true;//默认开关是开着的
                        for(int i=0;i<=arr.length-j-1;i++){
                                count++;//只要进行比较,就加1操作。
                                if(arr[i]>arr[i+1]){//前面的数比后面的数大,才进行交换:
                                        //交换
                                        
                                        t=arr[i];
                                        arr[i]=arr[i+1];
                                        arr[i+1]=t;
                                        flag=false;//只要交换了,开关就关上
                                }
                        }
                        if(flag){//假如一直没有交换,那么这个开关一直是开着的,一直是开着证明数组是有序的,那么不再进行下一轮比较了!break停止循环即可
                                break;
                        }
                }
                //排序后输出:
                System.out.println(Arrays.toString(arr));
                System.out.println("一共进行了"+count+"次比较");
        }
}

选择排序

import java.util.*;
public class TestArray14{
        public static void main(String[] args){
                int[] arr={11,1,22,15,-8};
                
                for(int j=0;j<=arr.length-2;j++){
                        int minIndex=j;
                        for(int i=(j+1);i<=arr.length-1;i++){
                                if(arr[i]<arr[minIndex]){
                                        minIndex=i;
                                }
                                
                        }
                        if(minIndex!=j){
                                //交换:
                                int t;
                                t=arr[j];
                                arr[j]=arr[minIndex];
                                arr[minIndex]=t;
                        }
                }
                System.out.println(Arrays.toString(arr));
                
                /*
                //第1趟:
                int minIndex=0;
                for(int i=1;i<=arr.length-1;i++){
                        if(arr[i]<arr[minIndex]){
                                minIndex=i;
                        }
                        
                }
                if(minIndex!=0){
                        //交换:
                        int t;
                        t=arr[0];
                        arr[0]=arr[minIndex];
                        arr[minIndex]=t;
                }
                
                //第2趟:
                int minIndex=1;
                for(int i=2;i<=arr.length-1;i++){
                        if(arr[i]<arr[minIndex]){
                                minIndex=i;
                        }
                        
                }
                if(minIndex!=1){
                        //交换:
                        int t;
                        t=arr[1];
                        arr[1]=arr[minIndex];
                        arr[minIndex]=t;
                }
                
                //第3趟:
                int minIndex=2;
                for(int i=3;i<=arr.length-1;i++){
                        if(arr[i]<arr[minIndex]){
                                minIndex=i;
                        }
                        
                }
                if(minIndex!=2){
                        //交换:
                        int t;
                        t=arr[2];
                        arr[2]=arr[minIndex];
                        arr[minIndex]=t;
                }
                
                //第4趟:
                int minIndex=3;
                for(int i=4;i<=arr.length-1;i++){
                        if(arr[i]<arr[minIndex]){
                                minIndex=i;
                        }
                        
                }
                if(minIndex!=3){
                        //交换:
                        int t;
                        t=arr[3];
                        arr[3]=arr[minIndex];
                        arr[minIndex]=t;
                }
                */
                
        }
}

选择排序:一轮下来,只交换一次!

【2】将排序的方法抽取出来为一个sort方法

扩展:时间复杂度和稳定性

冒泡排序:
时间复杂度:
【1】计算最糟糕情况:为什么时间复杂度为O(N^2)
要排序的个数n
第一层for
执行了n次
第二层for
第一次比较了n-1次
第二次比较了n-2次
....
第n-1次比较了1次

执行的总次数

count=3(1+2+3+4+.....+n-1)(n为正整数)
打印for
执行了n次
所有总的次数:
sum=n+3(1+2+3+4+...+n-1)+n+(n-n)=3(1+2+3+4+...+n-1+n)-n
如果n为偶数
sum=3* n/2*(n+1) -n=3/2(n^2+n)-n=1/2(3n^2+n)
如果n为奇数
sum=3((n-1)/2 *n+(n+1)/2)-n=3/2(n^2+1)-n=1/2(3n^2-2n+3)
所以最差的情况的时间复杂度为O(N^2)
【2】计算最好情况:为什么时间复杂度为O(N)
一轮下来发现数组是有序的,循环停止,总执行次数:sum=n 
所以最好的情况的时间复杂度为O(N)

 快速排序

思路:https://www.bilibili.com/video/av26394341/?p=8

代码:https://www.bilibili.com/video/av26394341/?p=9

查找

顺序查找

折半查找(二分法查找)

 

import java.util.*;
public class TestArray16{
        public static void main(String[] args){
                //给定一个数组---》前提:---》必须是有序的:
                int[] arr={1,3,5,7,9,11,13};
                int index=binarySearch(arr,111);
                if(index>=0){
                        System.out.println("我猜到的这个数对应的索引是:"+index);
                }else{
                        System.out.println("没有找到这个数!");
                }
        }
        
        public static int binarySearch(int[] arr,int item){//在arr数组中找item这个数对应的索引
                //找:
                int low=0;
                int high=arr.length-1;
                int index=-1;//最终我要找的目标:赋予初始值-1--》为了防止找不到
                while(low<=high){
                        int mid=(low+high)/2;
                        int guess=arr[mid];
                        if(guess==item){
                                index=mid;
                                break;
                        }
                        if(guess>item){
                                high=mid-1;
                        }
                        if(guess<item){
                                low=mid+1;
                        }
                }
                return index;
                
        }
        
}

【7】递归方式代码:

public class Test03 {
        public static void main(String[] args) {
                //先给定一个有序的数组:
                int[] arr={1,2,3,4,5,6,7,8,9};
                int index=binarySearch(arr,8,0,arr.length-1);
                System.out.println(index);
        }
        
        public static int binarySearch(int[] arr,int item,int low,int high){
                if(low>high){//递归结束条件
                        return -1;
                }
                System.out.println("---");
                int mid=(low+high)/2;
                int guess=arr[mid];//猜不是瞎猜 永远猜数组中间那个数
                if(guess>item){
                        return binarySearch(arr,item,low,mid-1);
                }else if(guess==item){
                        return mid;
                }else{
                        return binarySearch(arr,item,mid+1,high);
                }
                
        }
}

【8】总结:
1.按照索引找数据:直接arr[i]最快 一步到位
2.按照数据找索引:暂时看折半查找效率很高,但是以后会学习:结构哈希表的查找,也是一步到位了(集合中讲解)

7、面向对象

 类和对象


/**
 * 我现在创建了一个类,类的名字是:Person
 */
public class Person {
    //名词--属性---成员变量---filed
    String name;//姓名
    int age;//年龄
    double height;//身高
    char sex;//性别
    //建议:我们只写跟业务逻辑相关的属性和方法
    //动词--方法---成员方法----method
    //吃饭
    public void eat(){
        System.out.println("我可以吃饭");
    }
    //睡觉
    public void sleep(String address){
        System.out.println("我在"+address+"睡觉");
    }
    //自我介绍
    public String introduce(){
        return "我的名字是:"+name+",我的年龄是:"+age+",我的身高是:"+height+",我的性别是:"+sex;
    }
}

 

/**
测试类:Test
 */
public class Test {
    public static void main(String[] args) {
        //创建对象:
        Person p1=new Person();
        //对p1这个对象的属性进行赋值:
        p1.name="露露";
        p1.age=19;
        p1.height=169.4;
        p1.sex='女';
        //对对象的属性进行读取(使用)
        System.out.println(p1.age);
        System.out.println(p1.height);
        //对方法进行调用:
        p1.eat();
        p1.sleep("寝室");
        String str=p1.introduce();
        System.out.println(str);
        //再创建一个对象:
        Person p2=new Person();
        p2.name="刚刚";
        p2.age=20;
        p2.height=180.5;
        p2.sex='男';
        String str02=p2.introduce();
        System.out.println(str02);
    }
}

构造器


public class Student {
    //属性
    int age;
    String name;
    double height;
    //方法
    public String introduce(){
        return "这个学生的名字是:"+name+",年龄是:"+age+",身高:"+height;
    }
    public void eat(){
        System.out.println("我可以吃饭。。");
    }
   
    //构造器的重载:
    public Student(String name,int age,double height){
        //当形参和属性名字相同时,会发生就近原则
        this.name=name;
        this.age=age;
        this.height=height;
    }
}
public class Test {
    public static void main(String[] args) {
        //创建一个学生类的具体的对象:
        Student s=new Student("露露",21,160.5);
        System.out.println(s.name);
        Student s2=new Student();
    }
}

局部变量和成员变量

区别1:代码中位置不同
         成员变量:类中定义的变量
         局部变量:方法中定义的变量  代码块中定义的变量
区别2:内存中位置不同
         成员变量:堆内存
         局部变量:栈内存        
区别3:是否有默认值
         成员变量:有
         局部变量:没有
区别4:代码的作用范围(空间)
         成员变量:当前类的很多方法
         局部变量:当前一个方法(当前代码块) 
区别5:作用时间不同
         成员变量:当前对象从创建到销毁
         局部变量:当前方法从开始执行到执行完毕

public class Demo {
    int age;//成员变量---》属性
    int a=99;
    public void eat(){
        int num1=10;//局部变量----》必须要进行初始化
        System.out.println(num1);
        int a=100;
        System.out.println(a);//就近原则,指的是局部变量a
        System.out.println(this.a);
    }
}

内存分析

 

 

 

 

 this

【2】利用debug测试一下this的存在,this就是指向:当前对象:
在调用构造器的时候:this指向:正在创建的那个对象
在调用普通方法的时候,this指向:正在调用方法的那个对象
总结:this就是指向对象自身


【3】代码:
(1)this修饰属性
(2)this修饰方法  this.
(3)this修饰构造器 this(传入实参)---》this修饰构造器必须放在第一行。????

public class Student {
    //构造器
    //定义一个空构造器:
    public Student(){
    }
    public Student(String name,int age){
        this(name);
        this.age=age;
       // this.name=name;
    }
    public Student(String name){
        this.name=name;
    }
    //属性
    String name;
    int age;
    //方法
    public void eat(){
        System.out.println("我可以吃饭。。");
        System.out.println(this.name);
        System.out.println(name);//this.相当与省略不写了。
    }
    public void play(){
        this.party();
        party();//this.可以省略不写:
        System.out.println("洗澡");
    }
    public void party(){
        System.out.println("吃饭");
        System.out.println("唱歌");
    }
    public static void main(String[] args) {
        Student s=new Student("露露",18);
        s.play();
    }
}

static

【1】static修饰变量:

在类第一次被加载的时候,就将static修饰的内容加载入方法区中,它是先于对象存在的,不依托于一个对象的。我们对static修饰的变量最好的访问方式为:类名.属性名  (Test.sid)

public class Test {
    //属性:
    int id;
    static int sid;
    public static void main(String[] args) {
        /*
        //创建对象:
        Test t1=new Test();
        t1.id=10;
        t1.sid=10;
        Test t2=new Test();
        t2.id=20;
        t2.sid=20;
        Test t3=new Test();
        t3.id=30;
        t3.sid=30;
        //对属性进行读取:
        System.out.println(t1.id);//10
        System.out.println(t2.id);//20
        System.out.println(t3.id);//30
        System.out.println(t1.sid);//30
        System.out.println(t2.sid);//30
        System.out.println(t3.sid);//30
*/
        Test.sid=10;
        System.out.println(Test.sid);
    }
}

【2】习题:
告诉我们:并不是所有的属性都要加上static修饰,要看自己题的需求。
假如你要是所有属性都用static修饰了,那么它是比较消耗内存的。

public class Student {
    String name;
    int age;
    static String school;//学生所在的学校
    public static void main(String[] args) {
        Student.school="清华大学";
        //创建一个学生对象:
        Student s1=new Student();
        s1.name="A同学";
        s1.age=20;
        //s1.school="清华大学";
        Student s2=new Student();
        s2.name="B同学";
        s2.age=19;
        //s2.school="清华大学";
        Student s3=new Student();
        s3.name="C同学";
        s3.age=20;
        //s3.school="清华大学";
        System.out.println(s2.school);
    }
}

【3】static修饰方法:
static修饰方法,也是在类被加载的时候加载入方法区的,它也是先于对象存在的,所以此时还没有对象呢。最好的调用方式:类名.方法名
所以我们不可以:不可以在static中用this、 
                            不可以在static修饰的方法中去访问非静态的变量
                            不可以在static修饰的方法中去访问非静态方法
对于普通的方法,我们必须创建对象,用对象去调用。
对于静态的方法,我们可以:(1)类名.方法名  (2)创建对象,对象名.方法名
总结:static必须找static

【4】块:

public class Test {
   ///类的组成:属性,方法,构造器,代码块(普通块,构造块,静态块,同步块)
    //属性
    int age;
    static int sage;
    //方法
    public void eat(){
        {
            System.out.println("这是一个普通块。");
            int a=10;
        }
        //System.out.println(a);
        if(1<8){
            int a=20;
        }
        for(int i=0;i<=10;i++){
            int a=30;
        }
    }
    //构造器
    public Test(){
        System.out.println("这是Test类的空构造器");
    }
    //构造块
    {
        System.out.println("这是一个构造块");
    }
    static{
        System.out.println(sage);
        System.out.println("这是一个静态块");
    }
    public static void main(String[] args) {
        Test t1=new Test();
        Test t2=new Test();
        Test t3=new Test();
    }
}

 三大特性

封装:提高了代码的安全性
继承:提高了代码的复用性
多态:提高了代码的扩展性

【1】生活案例:ATM,电线等
【2】什么叫做封装:
将某些东西进行隐藏,然后提供相应的方式进行获取。
【3】封装的好处:
提高代码的安全性
【4】怎么进行封装:
以属性为例:
(1)将属性私有化(private int age) --->将属性利用权限修饰符进行修饰:private
        利用修饰符来控制权限  ,一旦控制了以后其他人就不可以随意的获取。
(2)提供公有的方法让别人来访问
(3)即使是访问也不是随便的访问,因为我在方法中进行了限制。
【5】引入代码:


public class Test {
    public static void main(String[] args) {
        Girl g = new Girl();
        g.shezhiage(32);
        System.out.println(g.quduage());//18
        //g.age=19;
        //System.out.println(g.age);
    }
}


class Girl {//女孩
    //属性:
    private int age;

    //方法:设置年龄:
    public void shezhiage(int age) {
        if (age >= 30) {
            this.age = 18;
        } else {
            this.age = age;
        }
    }

    //方法:读取年龄:
    public int quduage() {
        return age;
    }
}

package com.lee.reggie.common;

public class Test {
    public static void main(String[] args) {
        //创建对象:
        Student s = new Student();
        s.setAge(190);
        s.setName("nana");
        s.setSex("人妖");
        System.out.println(s.introduce());
        //再创建一个对象:
        Student s2 = new Student("feifei", 190, "人妖");
        System.out.println(s2.introduce());
    }
}

class Student {
    private String name;
    private int age;
    private String sex;

    public Student() {
    }

    public Student(String name, int age, String sex) {
        this.name = name;
        this.setAge(age);
        this.setSex(sex);
    }

    //getter方法:
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getSex() {
        return sex;
    }

    //setter方法:
    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        if (age >= 1 && age <= 120) {
            this.age = age;
        } else {
            this.age = 40;
        }
    }

    public void setSex(String sex) {
        //sex.equals("男")
        if ("男".equals(sex) || "女".equals(sex)) {//如果性别是男或女 才是正常的
            this.sex = sex;
        } else {
            this.sex = "男";
        }
    }

    //自我介绍:
    public String introduce() {
        return "我的名字是:" + name + ",年龄是:" + age + ",我的性别是:" + sex;
    }
}

 继承

【1】类是对对象的抽象
举例:你的粉色杯子,他的红色杯子,我的紫色杯子,小鼠标,键盘----》具体的对象
---》进行类的抽取:找共同的东西:
 你的粉色杯子,他的红色杯子,我的紫色杯子---》杯子的类
【2】继承是对类的抽象
举例:
学生类:Student:
        属性:年龄,姓名,学生编号
        方法:吃饭,喝酒,学习,自我介绍
教师类:Teacher:
        属性:年龄,姓名,教师编号
        方法:吃饭,喝酒,教学,自我介绍
员工类:Employee:
        属性:年龄,姓名,员工编号
        方法:吃饭,喝酒,工作,自我介绍

共同的东西:
人类:
       属性:年龄,姓名
       方法:吃饭,喝酒,自我介绍    

学生类/教师类/员工类  继承自  人类:

学生是一个人
教师是一个人
员工是一个人


狗类:
       属性:年龄,姓名,身高
       方法:吃饭,喝酒,汪汪叫   

狗是一个人


继承  必须在合理的范围中进行的向上抽取  


【3】写代码:学生类 继承自  人类  为案例:
学生类---》子类
人类----》父类
---》先写父类,再写子类  (子类对父类进行扩展)

package com.lee.reggie.common;

public class Test {
    public static void main(String[] args) {
        Student s = new Student("nana", 18, 1001);
        System.out.println("我的姓名是:" + s.getName() + ",我的年龄是:" + s.getAge() + ",我的学号是:" + s.getSno());
        s.eat();
        s.drink();
        s.study();
    }
}

class Person {
    //属性:
    private int age;
    private String name;

    //方法:
    //吃饭
    public void eat() {
        System.out.println("我可以吃饭");
    }

    //喝酒
    public void drink() {
        System.out.println("我可以喝酒");
    }

    //加入setter,getter方法:
    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    //自我介绍
    public String introduce() {
        return "我可以自我介绍";
    }

    //构造器:
    public Person() {
    }

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }
}


class Student extends Person {
    //属性:
    private int sno;//学号

    //方法:
    public void study() {
        System.out.println("我可以学习");
    }

    public int getSno() {
        return sno;
    }

    public void setSno(int sno) {
        this.sno = sno;
    }

    //构造器:
    public Student(String name, int age, int sno) {
        super.setAge(age);//调用父类的方法
        super.setName(name);//调用父类的方法
        this.sno = sno;
    }
}

好处:提高代码的复用性。

java继承具备传递性:
我们的代码:Student继承了Person类,Person类又继承了Object类。
Object是所有类的根基父类,一个类一定是直接或者间接的继承自Object类
Student--->Person---->Object


java 只有单继承:一个类只能继承一个类 

继承内存

 

 权限修饰符

 

 

 

 属性,方法修饰符:四种:private,default,protected,public 
但是我们一般: 属性用private修饰,方法用public修饰


类前面:只有两种:default,public 

重写和重载

【1】重写:当子类对父类的方法不满意的时候,要对父类的方法进行重写。
【2】重写需要注意什么?
要求:子类方法的名字,和形参列表(顺序,类型,个数)必须跟父类一模一样。

【3】重载和重写区别:

 

 

 super

 

 【3】加深练习:练习:this,super:

package com.lee.reggie.common;

public class Test {
    public static void main(String[] args) {
        B b = new B();
        b.b();
    }
}

class A {
    int age = 10;

    public void a() {
        int age = 20;
        this.age = 30;
        age = 40;
    }
}

class B extends A {
    int age = 50;

    public void b() {
        int age = 60;
        this.age = 70;
        age = 80;
        super.age = 90;
        super.a();
        System.out.println(age);
        System.out.println(this.age);
        System.out.println(super.age);
    }
}


super:修饰:修饰属性,修饰方法。


【4】super修饰构造器:
(1)每个构造器的内部,第一句都是在调用super父类的构造器进行初始化,
假如你没有显示编写super调用,那么默认分配的是调用父类空构造器:super()
(2)调用父类super构造器  必须放在第一行 :我要先对父类初始化  再是子类。
(3)this修饰构造器 和  super修饰构造器  要是都存在,就冲突了,只能保留一个

package com.lee.reggie.common;

public class Test {
    public static void main(String[] args) {
        //利用空构造器创建对象:
        Student s = new Student();
        //利用有参构造器创建对象:
        Student s2 = new Student("lili", 19, 160.4, 1001);
    }
}

class Person {
    String name;
    int age;
    double height;

    public Person() {
        super();
    }

    public Person(String name, int age, double height) {
        super();
        this.name = name;
        this.age = age;
        this.height = height;
    }
}


class Student extends Person {
    int sno;

    public Student() {
        super();//调用父类的构造器
    }

    public Student(int sno) {
        super();
        this.sno = sno;
    }

    public Student(String name, int age, double height, int sno) {
        //super();
        super(name, age, height);
        /*this.name=name;
        this.age=age;
        this.height=height;*/
        //this.sno=sno;
        //this(sno);
    }
}

继承条件下构造方法执行过程

 toString

【2】我现在输出这个对象,我想得到的是啥?
我想得到的是对这个对象的“介绍”。
出现了一个问题:子类对父类提供toString方法不满意,不满意就要重写:

public class Student /*extends Object*/{
    int age;
    String name;
    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }
    public String toString(){
        return "这是一个学生对象:name="+name+",age="+age;
    }
    public static void main(String[] args) {
        int a=10;
        System.out.println(a);//输出基本数据类型的数值
        Student s=new Student(19,"lili");//引用数据类型
        System.out.println(s);//com.bjsxt.test01.Student@4554617c
        System.out.println(s.toString());//com.bjsxt.test01.Student@4554617c
        //toString()是谁定义的呀?
    }
}

 

equals 

 【1】equals:
将对象进行比较的(比较的具体的属性的值,而不是比较地址)
一般来说,Obejct提供的equals我们不满意,我们就要重写。

public class Cat {//猫
    double weight;//体重
    String type;//品种
    int age;//年龄
    public Cat(double weight, String type, int age) {
        this.weight = weight;
        this.type = type;
        this.age = age;
    }
    public boolean equals(Object obj) {//c1.equals(c2)
        //A instanceof B :判断A这个对象是否是B这个类的实例
        if(obj instanceof Cat){//传进来的是一只猫
            Cat other=(Cat)obj;//暂时这一步未知
            //c1的体重=c2的体重 并且 c1的类型=c2的类型  并且  c1的年龄 =c2的年龄 ---》认为两只猫一样
            if(this.weight==other.weight&&this.type==other.type&&this.age==other.age){
                return true;
            }
        }
        return false;
    }
    public static void main(String[] args) {
        Cat c1=new Cat(10.4,"蓝猫",1);
        Cat c2=new Cat(10.4,"蓝猫",2);
        System.out.println(c1==c2);//一定是一个false
        //比较的是内容:
        System.out.println(c1.equals(c2));
        Dog d=new Dog();
        System.out.println(c1.equals(d));
    }
}

 扩展

面试题:
【1】请写出Object类常用的6个方法及其作用
toString(); 将对象转换为字符串格式
equals(null);判断两个对象的内容是否相同
hashCode(); 哈希码  (集合)哈希表
getClass(); 得到一个对象或者类的结构信息(反射)
wait(); 等待(多线程)
notify(); 唤醒任何一个(多线程)
notifyAll();唤醒所有(多线程)

【2】以上方法是Object类的所有方法吗?
      是所有的public方法
      除了public方法外,还有其他:
protected void finalize() throws Throwable { } 垃圾回收器相关方法
protected native Object clone() throws CloneNotSupportedException; 克隆  快速复制  原型设计模式
private static native void registerNatives();
native  本地的
所有native修饰的方法都没有方法体;native本地的
Java不是完美的,Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),
为此Java使用native方法来扩展Java程序的功能。


native扩展:
一. 什么是Native Method
  简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern "C"告知C++编译器去调用一个C的函数。


二.为什么要使用Native Method
  java使用起来非常方便,然而有些层次的任务用java实现起来不容易,或者我们对程序的效率很在意时,问题就来了。

  与java环境外交互:
  有时java应用需要与java外面的环境交互。这是本地方法存在的主要原因,你可以想想java需要与一些底层系统如操作系统或某些硬件交换信息时的情况。本地方法正是这样一种交流机制:它为我们提供了一个非常简洁的接口,而且我们无需去了解java应用之外的繁琐的细节。

  与操作系统交互:
  JVM支持着java语言本身和运行时库,它是java程序赖以生存的平台,它由一个解释器(解释字节码)和一些连接到本地代码的库组成。然而不管怎 样,它毕竟不是一个完整的系统,它经常依赖于一些底层(underneath在下面的)系统的支持。这些底层系统常常是强大的操作系统。通过使用本地方法,我们得以用java实现了jre的与底层系统的交互,甚至JVM的一些部分就是用C写的,还有,如果我们要使用一些java语言本身没有提供封装的操作系统的特性时,我们也需要使用本地方法。

三.JVM怎样使Native Method跑起来:
    我们知道,当一个类第一次被使用到时,这个类的字节码会被加载到内存,并且只会回载一次。在这个被加载的字节码的入口维持着一个该类所有方法描述符的list,这些方法描述符包含这样一些信息:方法代码存于何处,它有哪些参数,方法的描述符(public之类)等等。
    如果一个方法描述符内有native,这个描述符块将有一个指向该方法的实现的指针。这些实现在一些DLL文件内,但是它们会被操作系统加载到java程序的地址空间。当一个带有本地方法的类被加载时,其相关的DLL并未被加载,因此指向方法实现的指针并不会被设置。当本地方法被调用之前,这些DLL才会被加载,这是通过调用java.system.loadLibrary()实现的。

类之间的关系

 

 

public class Test {
    public static void main(String[] args) {
        //有一个具体的男孩:
        Boy b=new Boy();
        //有一个具体的女孩:
        Girl g=new Girl();
        //谈恋爱:
        g.love(b);
        //中华儿女千千万 不行咱就换:
        Boy b2=new Boy();
        g.love(b2);
        //小女孩跟妈妈聊天:
        //具体的妈:
        g.name="lili";
        g.age=10;
        g.m=new Mom();
        g.say();
    }
}

class Mom {
    public void wechat(){
        System.out.println("跟妈妈微信聊天。。。");
    }
}

class Boy {
    //有钱:
    public void havemoney(){
        System.out.println("买买买。。。180 180 180 180");
    }
}


class Girl {
    String name;
    int age;
    double weight;
    Mom m;//将另一个类作为属性
    //找男朋友:
    public void love(Boy b){//将另一个类作为形参传入
        b.havemoney();
    }
    //跟妈妈聊天:
    public void say(){
        m.wechat();
    }
}

多态

多态跟属性无关!

父类---》再有子类:   继承 
有子类--》提取父类:  泛化

【1】啥叫多态?
多种状态

【2】多态的好处:
提高了代码的扩展性,你增加代码,对其他类的影响降到了最低
(多态可以提高扩展性,但是没有达到最好,---》反射)

【3】多态构成要素:
(1)继承  Cat  extends Animal
(2)重写  shout(){猫叫}
(3)父类引用指向子类对象   Animal an=new Cat();
Cat c=new Cat();
Animal an=c;  ---->Animal an=new Cat();


【4】代码:

public class Test {
    public static void main(String[] args) {
        //具体的小女孩
        Girl g=new Girl();
        //具体的小动物:(我想让动物是一只具体的狗)
        Fish f=new Fish();
        Animal an=f;//Animal an=new Fish();
        //小女孩跟小动物玩:
        g.play(an);
    }
}


class Animal {
    public void shout(){
        System.out.println("我是小动物,我会叫。");
    }
}


 class Dog extends Animal{
    //叫
    public void shout(){
        System.out.println("我是小狗,我可以旺旺叫。。");
    }
    //看家护院
    public void guard(){
        System.out.println("我是小狗,我可以保护我的主人。。");
    }
}


class Cat extends Animal {
    //叫
    public void shout(){
        System.out.println("我是小猫,我可以喵喵叫。。");
    }
    //挠人
    public void scratch(){
        System.out.println("我是小猫,我可以挠人。。");
    }
}

 class Fish extends Animal {
    public void shout(){
        System.out.println("我是鱼,我可以吐泡泡。。");
    }
}


class Girl {
    //跟猫玩:
    /*public void play(Cat c){
        c.shout();
    }*/
    //跟狗玩:
    /*public void play(Dog d){
        d.shout();
    }*/
    ///小动物:
    public void play(Animal an){//Animal an=new Fish();
        an.shout();
    }
}

内存分析

 向上转型,向下转型

 

 

 简单工厂设计模式

public class Test {
    public static void main(String[] args) {
        //创建一个鸟具体的对象:
        Bird b=new Bird(1,"红色");
        System.out.println(b.show());
        b.fly();
    }
}



class Animal {
    private int age;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    //动物的自我展示:
    public String show(){
        return "我是一只动物!";
    }
    //构造器:
    public Animal() {
    }
    public Animal(int age) {
        this.age = age;
    }
}


 class Bird extends Animal{
    private String color;
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    public Bird() {
    }
    public Bird(int age, String color) {
        super(age);
        this.color = color;
    }
    //特有的方法:
    public void fly(){
        System.out.println("我是小鸟我可以展翅翱翔。。");
    }
    public String show(){
        return "我是一只"+color+"的鸟,\n今年"+getAge()+"岁了!";
    }
}

 

package com.lee.reggie.common;

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        //1.键盘录入你的选择:
        Scanner sc = new Scanner(System.in);
        System.out.print("请选择想要制作的披萨(1.培根披萨 2.海鲜披萨):");
        int order = sc.nextInt();
        //2.通过披萨店给我生产披萨:
        Pizza p = PizzaShop.getPizza(order);
        //3.将披萨信息展示:
        System.out.println(p.showPizza());
    }
}

class Pizza {
    private String name;//名称
    private int size;//大小
    private int price;//价格

    public String getName() {
        return name;
    }

    public int getSize() {
        return size;
    }

    public int getPrice() {
        return price;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public Pizza() {
    }

    public Pizza(String name, int size, int price) {
        this.name = name;
        this.size = size;
        this.price = price;
    }

    //披萨信息展示:
    public String showPizza() {
        return "这是一个披萨!";
    }
}


class BaconPizza extends Pizza {//培根披萨
    private int weight;//重量:克数

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public BaconPizza(String name, int size, int price, int weight) {
        super(name, size, price);
        this.weight = weight;
    }

    public String showPizza() {
        return "名称:" + getName() + "\n大小:" + getSize() + "\n价格:" + getPrice() + "\n克数:" + weight;
    }
}


class SeaFoodPizza extends Pizza {
    private String dosing;

    public String getDosing() {
        return dosing;
    }

    public void setDosing(String dosing) {
        this.dosing = dosing;
    }

    public SeaFoodPizza(String name, int size, int price, String dosing) {
        super(name, size, price);
        this.dosing = dosing;
    }

    public String showPizza() {
        return "名称:" + getName() + "\n大小:" + getSize() + "\n价格:" + getPrice() + "\n配料:" + dosing;
    }
}

class PizzaShop {//披萨商店

    //提供披萨:
    public static Pizza getPizza(int order) {
        Scanner sc = new Scanner(System.in);
        Pizza p = null;
        //2.根据你的选择开始制作:
        if (order == 1) {//1.培根披萨
            System.out.println("请录入培根的克数:");
            int weight = sc.nextInt();
            System.out.println("请录入披萨的大小:");
            int size = sc.nextInt();
            System.out.println("请录入披萨的价格:");
            int price = sc.nextInt();
            //将录入的信息封装成为一个培根披萨的对象:
            p = new BaconPizza("培根披萨", size, price, weight);
        }
        if (order == 2) {//2.海鲜披萨
            System.out.println("请录入配料信息:");
            String dosing = sc.next();
            System.out.println("请录入披萨的大小:");
            int size = sc.nextInt();
            System.out.println("请录入披萨的价格:");
            int price = sc.nextInt();
            //将录入的信息封装成为一个海鲜披萨的对象:
            p = new SeaFoodPizza("海鲜披萨", size, price, dosing);
        }
        return p;
    }
}

final

public class Test {
    public static void main(String[] args) {
        //1......
        final int A=10;//基本数据类型被final修饰,它的数值不可以被修改。
        // A=20;
        System.out.println(A);
        //当一个变量被final修饰,它就变成了一个常量,它的值不可以再被修改。
        //建议名字全部大写
        //2......
        final Dog d=new Dog();//引用数据类型被final修饰,它的地址值不可以被修改。
        d.age=10;
        d.age=20;
        //d=new Dog();--->不可以
        //3.......
        final Dog d2=new Dog();
        a(d2);//可以
        //4.....
        final Dog d3=new Dog();
        b(d3);
        Dog d4=new Dog();
        b(d4);
    }
    public static void a(Dog d){
        d=new Dog();//可以
    }
    public static void b(final Dog d){
       // d=new Dog(); 不可以
    }
}

 【2】final修饰类:如果一个类被final修饰,那么这个类就不可以被继承。

【3】final修饰方法:
(1)如果一个方法被final修饰,那么子类不可以重写这个方法
(2)虽然子类不能重写了,但是调用都是可以的!

【4】查看源码:Math类:
(1)final修饰属性:这个值不让其他人更改
(2)final修饰方法:不能被重写
(3)final修饰类:不能被继承
(4)发现Math中的构造器被private修饰了:

 抽象类、抽象方法

【1】为什么需要抽象类? 如何定义抽象类?
是一种模版模式。
抽象类为所有子类提供了一个通用模版,子类可以在这个模版基础上进行扩展。
通过抽象类,可以避免子类设计的随意性。通过抽象类,我们就可以做到严格限制子类的设计,使子类之间更加通用。

public abstract class Person {
    //1.在一个类中,有一部分方法,子类对他永远满意,直接用,不用重写
    public void eat(){
        System.out.println("吃食物");
    }
    //2.在一个类中,还有一部分方法,无论怎么写子类都不满意,都要对它进行重写。
    //2.对于这样的方法,方法体就没有必要再写了
    //2.假如一个方法没有方法体,只有方法的声明,那么这个方法就变成了一个抽象方法
    public abstract void say();
    public abstract  void sleep();
}
//5.抽象类可以被继承吗?可以的,必须重写全部的抽象方法。
//6.假如子类没有重写全部的抽象方法,那么这个类也可以变为一个抽象类。
class Student extends Person{
    @Override
    public void say() {
        System.out.println("说普通话。。");
    }
    @Override
    public void sleep() {
    }
}
class Test{
    public static void main(String[] args) {
        //7.可否创建抽象类的对象:抽象类不可以创建对象。
        //Person p=new Person();
        Student s=new Student();
        s.eat();
        s.say();
        s.sleep();
        //8.就想创建抽象类的对象:
        Person p=new Student();//多态
    }
}

【2】面试题:
(1)抽象类不能创建对象,那么抽象类中是否有构造器?
必须有构造器,因为这个构造器不是给抽象类用的,而是给子类创建对象的时候调用的。


(2)抽象类可否被final修饰?
不可以的
final修饰不能被子类继承,但是抽象类就是给子类定义模板的。

接口


/*
//1.一个类假如是抽象类,那么其中可以有普通方法,也可以有抽象方法。
//2.当一个类中全部是抽象方法的时候,就变成了一个接口。(JDK1.8)
//3.看着好像接口是特殊的抽象类,但是实际上  接口是接口,类是类。--》接口不是类。
//4.引用数据类型:类,数组,接口
//5.接口中有构造器吗?没有
//6.如何定义一个接口?interface
//7.接口中有啥啊?(JDK.1.8之前:)
(1)常量:固定的修饰符:public static final
(2)抽象方法:public abstract
前面的确是有固定的修饰符,但是假如不写,系统会默认帮助我们补全。
建议:自己全部都加上。
 */
public interface Test {
    //定义常量:
    public static final int NUM=10;
    public final int NUM2=20;
    //定义抽象方法:
    public abstract void eat();
    abstract void sleep();
}
interface Test2{
    public abstract  void study();
    public abstract  void drink();
}
/*
8.类和接口之间是什么关系呢?实现关系:implements
9.一个类要是实现一个接口,必须要实现全部的抽象方法。
  Student--》实现类。
10.一个类可以实现多个接口。
   一个类只能单继承。
11.假如没有实现全部的抽象方法,那么这个类变成了一个抽象类。
12.一个类可以既实现接口又继承其他类吗?可以:
但是格式必须:先继承再实现:
extends Person implements Test,Test2
13.疑问?为啥可以实现多个接口,但是继承只有一个?
 */
class Student extends Person implements Test,Test2 {
    @Override
    public void eat() {
        System.out.println("我可以吃饭");
    }
    @Override
    public void sleep() {
        System.out.println("我可以睡觉。");
    }
    @Override
    public void study() {
        System.out.println("我可以学习");
    }
    @Override
    public void drink() {
        System.out.println("我可以喝酒。");
    }
}
class Person{
}
class Demo{
    public static void main(String[] args) {
        //14.给接口创建对象:
        //Test t=new Test();
        Test t=new Student();//接口=实现类---》多态
        t.eat();
        //15.访问Test接口中的NUM常量:
        System.out.println(Test.NUM);
        Student s=new Student();
        System.out.println(s.NUM);
        System.out.println(Student.NUM);
    }
}


【2】继承和接口的区别(应用场景)

手机 是一个 照相机  。

手机    extends     照相机(安装胶卷) 

手机具备照相的能力


继承:“is-a”
接口:"has-a"

举例:
Fly接口:
飞机,小鸟,风筝

小鸟    extends Animal implements Fly接口


实现比较

 

 【4】比较:内部比较器:

public class Student implements Comparable{
    int age;
    String name;
    double height;
    public Student(int age, String name, double height) {
        this.age = age;
        this.name = name;
        this.height = height;
    }
    @Override
    public int compareTo(Object o) {//a.compareTo(b
        Student other=(Student)o;
        //按照年龄进行比较:
        //return a的年龄-b的年龄;
        //return this.age-other.age;
        //按照比较身高比较:
        //return a的身高-b的身高;
        //return ((Double)this.height).compareTo((Double)other.height);
        //按照姓名:
        //return this.name.compareTo(other.name);
        //按照年龄和身高比较:年龄不同比年龄就行了,年龄相同再比较身高。
        if(this.age-other.age!=0){
            return this.age-other.age;
        }else{
            return ((Double)this.height).compareTo((Double)other.height);
        }
    }
}


public class Test {
    public static void main(String[] args) {
        Student a=new Student(28,"Alili",178.5);
        Student b=new Student(19,"aanana",171.5);
        System.out.println(a.compareTo(b));
    }
}

【5】外部比较器:


public class Student{
    int age;
    String name;
    double height;
    public Student(int age, String name, double height) {
        this.age = age;
        this.name = name;
        this.height = height;
    }
}
class BiJiao implements Comparator{
    @Override
    public int compare(Object o1, Object o2) {
        //比较规则:比较两个人的年龄:
        Student a= ((Student) o1);
        Student b= ((Student) o2);
        return a.age-b.age;
    }
}
class BiJiao02 implements  Comparator{
    @Override
    public int compare(Object o1, Object o2) {
        //比较规则:比较两个人的身高:
        Student a= ((Student) o1);
        Student b= ((Student) o2);
        return ((Double)a.height).compareTo((Double)b.height);
    }
}


public class Test {
    public static void main(String[] args) {
        Student a=new Student(28,"Alili",178.5);
        Student b=new Student(19,"aanana",171.5);
        Comparator bj=new  BiJiao02();//多态
        int num= bj.compare(a,b);
        System.out.println(num);
    }
}

【6】内部比较器和外部比较器哪个好?外部比较器
因为扩展性好,不同的比较规则要是用内部比较器写的话,就要来来回回的注释。

JDK1.8之前:接口中包含:
(1)常量:public static final
(2)抽象方法:public abstract

在JDK1.8之后,对于方法部分进行了扩展:
可以加入非抽象方法:
【1】方法被public default修饰:
PS:在接口中,要是default不写,出错。必须加上default
PS:在实现类中,要是重写接口中的default方法  ,必须不写,

public interface MyInterface {
    //抽象方法:
    public abstract  void a(int age);
    //非抽象方法:
    public default void b(){
        System.out.println("----MyInterface----b()------");
    }
}
class MyClass implements MyInterface {
    @Override
    public void a(int age) {
        System.out.println("----MyInterface---a----");
    }
    public void b(){
        System.out.println("----MyClass----b()------");
    }
}
class Test{
    public static void main(String[] args) {
        MyClass m=new MyClass();
        m.b();
    }
}

【2】可以加入静态方法:

public interface MyInterface {
    //抽象方法:
    public abstract  void a(int age);
    //非抽象方法:
    public static void b(){
        System.out.println("----MyInterface----b()------");
    }
}
class MyClass implements MyInterface {
    @Override
    public void a(int age) {
        System.out.println("----MyInterface---a----");
    }
    public static void b(){
        System.out.println("---MyClass----b()------");
    }
}
class Test{
    public static void main(String[] args) {
        MyClass m=new MyClass();
        m.b();
        MyInterface.b();
    }
}

【3】疑问:为啥要在接口中加入非抽象方法?
假如在接口中只能加入抽象方法,那么一旦更改接口中的抽象方法,那么所有的实现类就要全部更改,影响太大。那么在JDK1.8之后,可以加入非抽象方法,那么实现类就可以直接拿过来这个方法使用,无需改动实现类了,影响较小。

public interface A {
    void a();
    void b();
    public default void c(){
        System.out.println("----c----");
    }
}
class B implements  A{
    @Override
    public void a() {
        //c();可以
        //super.c();不可以
       // A.super.c();可以
    }
    @Override
    public void b() {
    }
}
class Test{
    public static void main(String[] args) {
        B b=new B();
        b.a();
    }
}
class C implements  A{
    @Override
    public void a() {
    }
    @Override
    public void b() {
    }
}

内部类

成员内部类

public class TestOuter {
    /*
    类中组成部分:
    属性,方法,构造器,代码块(普通块,静态块,构造块,同步块),内部类
内部类:1.成员内部类   4.匿名内部类。 不讲: 2.静态内部类  3.方法内部类
     */
    private int age;
    int a=10;
    public void eat(){
        {
            System.out.println("这是普通块");
        }
        //4.在外部类中访问内部类的属性:
        //System.out.println(name);不行
        TestInner t=new TestInner();
        System.out.println(t.name);//行
    }
    public TestOuter(){
    }
    {
        System.out.println("这是构造块");
    }
    static{
        System.out.println("静态块");
    }
    //1.成员内部类:前面的权限修饰符:public ,default,private,protected
    private class TestInner{
        String name;
        int a=20;
        public void sleep(){
            //3.内部类中可以访问外部类的属性:
            System.out.println(age);
            int a=30;
            //7.当局部变量和外部类,内部类属性重名时候如何访问:
            System.out.println(a);//30
            System.out.println(this.a);//20
            System.out.println(TestOuter.this.a);//10
        }
    }
    public static void main(String[] args) {
        //5.创建外部类对象:
        TestOuter to=new TestOuter();
        //6.创建内部类对象:
        //TestInner t=new TestInner();不行
        int age=to.age;
        TestInner ti=to.new TestInner();
    }
}

 匿名内部类

【1】应用:
在项目中,这个类只应用一次,那么就可以用匿名内部类。
---在java中,没有那么重要---》在安卓中用的多。
【2】代码:

public interface LianJiaHouse {
    //告诉你房子的位置
    public void address();
    //告诉你房子的价格
    public void price();
}


public class Bj implements LianJiaHouse{
    @Override
    public void address() {
        System.out.println("北京五环。。");
    }
    @Override
    public void price() {
        System.out.println("三万一平。。");
    }
}


public class Test {
    public static void main(String[] args) {
        Bj b1=new Bj();
        showHouse(b1);
        Bj b2=new Bj();
        showHouse(b2);
        Tj t1=new Tj();
        showHouse(t1);
        Tj t2=new Tj();
        showHouse(t2);
        //匿名内部类
        /*LianJiaHouse lj=new LianJiaHouse() {
            @Override
            public void address() {
                System.out.println("南京。。");
            }
            @Override
            public void price() {
                System.out.println("7亿。。");
            }
        };*/
        showHouse(new LianJiaHouse() {
            @Override
            public void address() {
                System.out.println("南京。。");
            }
            @Override
            public void price() {
                System.out.println("7亿。。");
            }
        });
    }
    public static void showHouse(LianJiaHouse lj){//多态的一种应用。
        lj.address();
        lj.price();
    }
}


public class Tj implements LianJiaHouse{
    @Override
    public void address() {
        System.out.println("天津市中心。。");
    }
    @Override
    public void price() {
        System.out.println("五万一平。。");
    }
}

【3】应用

public class Test {
    public static void main(String[] args) {
        Student a=new Student(28,"Alili",178.5);
        Student b=new Student(19,"aanana",171.5);
        /*Comparator bj=new  Comparator(){
            @Override
            public int compare(Object o1, Object o2) {
                Student a= ((Student) o1);
                Student b= ((Student) o2);
                return a.name.compareTo(b.name);
            }
        };
        int num= bj.compare(a,b);*/
       int num=new Comparator(){
            @Override
            public int compare(Object o1, Object o2) {
                Student a= ((Student) o1);
                Student b= ((Student) o2);
                return a.name.compareTo(b.name);
            }
        }.compare(a,b);
        System.out.println(num);
    }
}

垃圾回收机制

【1】对象空间的分配:
使用new关键字创建对象即可

【2】对象空间的释放:
传统的C/C++语言,需要程序员负责回收已经分配内存。显式回收垃圾回收的缺点:
程序忘记及时回收,从而导致内存泄露,降低系统性能。
程序错误回收程序核心类库的内存,导致系统崩溃。
Java语言不需要程序员直接控制内存回收,是由JRE在后台自动回收不再使用的内存,称为垃圾回收机制(Garbage Collection)。
可以提高编程效率。
保护程序的完整性。
其开销影响性能。Java虚拟机必须跟踪程序中有用的对象,确定哪些是无用的。

【3】垃圾回收细节:
垃圾回收机制只回收JVM堆内存里的对象空间。
现在的JVM有多种垃圾回收实现算法,表现各异。
垃圾回收发生具有不可预知性,程序无法精确控制垃圾回收机制执行。
可以将对象的引用变量设置为null,暗示垃圾回收机制可以回收该对象。
程序员可以通过System.gc()或者Runtime.getRuntime().gc()来通知系统进行垃圾回收,会有一些效果,但是系统是否进行垃圾回收依然不确定。
垃圾回收机制回收任何对象之前,总会先调用它的finalize方法(如果覆盖该方法,让一个新的引用变量重新引用该对象,则会重新激活对象)。
永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用。

这个方法做什么事?这个方法不是帮助我清理垃圾的,清理垃圾这件事是由JVM帮我完成的,这个方法就是在JVM帮我清理完垃圾之后,他会去调用这个方法。

public class Animal {
    int age;
   /* protected void finalize()
            throws Throwable{
        System.out.println("这个垃圾被清理了。");
    }*/
}

public class Test {
    public static void main(String[] args) {
        new Animal();
        new Animal();
        new Animal();
        new Animal();
        new Animal();
        //告诉人家帮我清理垃圾:
       /*for(int i=1;i<=100;i++){
           //System.gc();
           Runtime.getRuntime().gc();
       }*/
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值