 Hello, I'm Doug Schmidt, and I'd like to welcome you to the overview of our MOOC on Java for Android, where you'll learn how to apply Java programming language features and tools used in Android, which is the dominant platform for developing and deploying mobile apps. This knowledge will help you write apps for the millions of people around the world who use Android devices to direct them to the places they want to go, securely provide information about the people, locations, goods and services near them, and help them interact with the people they care about and do business with. The demand for Android app developers is large and growing, so you're making a wise investment in your future by completing this MOOC. Hi, I'm Jerry Roth. In this MOOC, we'll cover key object-oriented features that are supported by the Java programming language. These Java features enhance the clarity of an app by controlling its flow of execution, enhance app utility by enabling access to structured data, enhance app modularity by grouping related methods and fields into classes and interfaces that shield apps from implementation details that are likely to change, and enhance app extensibility by transparently customizing the behavior of existing classes via inheritance and polymorphism to meet new requirements. Hi, I'm Michael Walker. In this MOOC, you'll learn how to apply the Java features Jerry just outlined in the context of core Android components such as basic user interface elements and activities for displaying user-facing operations. You'll also learn how to create Android apps by using the integrated development environment provided by Android Studio, which comes bundled with many tools. Some of the tools we'll cover in this MOOC include a wizard for creating new apps, a visual editor for creating graphical user interfaces, an emulator for testing apps on your computer, and a debugger for locating errors in your code. Hi, I'm Julie Johnson. After completing this MOOC, you'll understand the key object-oriented features needed to program Java for Android as well as know how to install Android Studio and apply it and other tools to develop and debug Android apps. Java is a large and evolving language which contains new features that aren't yet supported in Android. However, the Java features we do cover will enable you to successfully complete the programming assignments in this MOOC and build the foundation to continue your mastery of Java and Android in other MOOCs offered on the Coursera platform. So let's get started. Welcome to the first module in our MOOC on Java for Android, which summarizes the MOOC's structure and contents, explains its prerequisites, workload and learning strategies, and presents an overview of key features in the Java language, focusing on its support for object-oriented programming concepts used to develop Android apps. After completing the lessons in this module, you'll be able to understand how to meet the course requirements, name the key object-oriented features in Java needed to write Android apps, and know where to find the information and resources you need to succeed in this MOOC. Much of this information is available in the Frequently Asked Questions or FACC website, so please read it carefully prior to watching the lessons in this MOOC. Welcome to the next lesson in this module, where we explain how this MOOC is organized and discuss steps you can take to master the material we cover. After completing this lesson, you'll understand the MOOC's structure and the main topics covered in each module of the MOOC, and recognize what's expected of you in terms of background knowledge and the steps you should take to complete the programming assignments and quizzes successfully. You'll also learn where to find more information on developing Android apps in Java effectively. Most topics we cover in this lesson apply to all the MOOCs in the specialization, so please watch it carefully. We'll start this lesson by summarizing the contents of this MOOC that follow the overview material in this first module. The second module presents an introduction to Android Studio, explaining how to install it, as well as how to apply it to develop simple apps written using the basic Java and Android features covered in this MOOC. The third module shows how to write other simple Android apps that use methods to define variables using primitive Java data types, assign values to those variables, and then output the variables to the Android display. Module 4 covers Java features that control the flow of execution through an app, including its various iteration constructs, such as for loops, while loops, and do while loops, as well as its conditional execution constructs, such as if-else statements. Module 5 provides more detail on Java features that enable apps to access structured data. These features include its built-in arrays, common classes in the Java collections framework, array list, and hash map, as well as the for-each loop, which can be used to iterate through each element in the Java collection. The sixth module covers Java features that group related operations and data into classes and interfaces. These features include Java's methods, generic parameters, fields, and exceptions. Module 7 examines Java features for customizing the behavior of existing classes via inheritance and polymorphism. These features make it possible to extend classes transparently and override their methods to customize the behavior. Finally, Module 8 guides learners through the creation of an Android app that implements a simple calculator, providing features for adding, subtracting, multiplying, and dividing numbers added by various means, such as a text string and via buttons on the Android user interface. The modules in this MOOC are structured uniformly. In particular, each module is composed of multiple lessons, which cover a set of related topics, such as Java classes, conditional statements, or the Android Studio app wizard. Each lesson is presented as a single lecture. Each lesson is composed of segments, including intros and outros that summarize the lesson's learning objectives, and one or more segments that present the technical content of the lesson. In-video quizzes periodically pop up to check if you've mastered the material covered in the lesson. If you download the videos and watch them locally on your computer, these quizzes won't appear, and some of the questions may show up on the weekly standalone quizzes, which we discuss later in this lesson. This MOOC specialization is intended both for learners who are just starting to program, as well as for learners switching to Java and or Android for the first time. The topics covered in the MOOC are based on material we teach to our undergrad students at Vanderbilt University. When teaching these courses to our students face-to-face, we can rely on them having taken the necessary prerequisites in the right order. In contrast, one challenge of teaching MOOCs is that we don't really know what you know, or whether you're prepared to master the topics we cover. We develop this specialization with certain expectations of learners who take the MOOCs. These expectations are summarized in the frequently asked questions or fact web page. In particular, this MOOC is intended for self-motivated learners interested in understanding both the concepts and practice of developing mobile apps. It's also intended for learners who are curious about the entire Android platform at the API level, as well as the inner workings of its software stack. Finally, we expect that learners are willing and able to read and follow the instructions in the MOOC assignments and announcements. We don't expect you to have a computer science background. However, we do expect you to have basic computer literacy skills, such as knowing how to send and receive emails, browse the web, participate in online discussion forums, and upload and download files on websites. Naturally, after you complete this MOOC specialization, we expect you to know how to use Android Studio, how to apply Java features needed to develop apps using core Android components, how to use the Git software version control system, as well as how and when to apply common software engineering concepts, methods, and programming skills to develop mobile apps for Android. There will be several programming assignments in this MOOC, all written in Java using Android Studio. The fact outlines which versions of Android and Java software to install so that everyone will have a common environment. All source code for the assignments and examples, as well as the source code for Java and Android, is available online via the links available at the MOOC GitHub website. The programming assignments will provide you with experience developing apps using a range of Java and Android features. The assignments may change a bit for each MOOC offering to keep the material fresh and aligned with enhancements in the Android platform. However, they are all designed to enable you to demonstrate mastery of each Java feature we cover. The stand-alone quizzes given weekly will be due at the end of the MOOC and are entirely auto graded. In contrast, the programming assignments will be assessed via a mixture of auto grading and peer grading, using the evaluation process discussed in the fact. If you're taking this MOOC to get a verified certificate, you're required to take the quizzes and complete the programming assignments, which will tally using the grading criteria described at the MOOC GitHub website. Learners taking this specialization are expected to devote time and effort each week to watch the lessons, take the quizzes, and complete the programming assignments. However, we recognize that everyone has different learning styles, backgrounds, motivations, aptitudes, and time commitments. Therefore, we can't precisely estimate how much time you'll require to complete the MOOCs in this specialization. In general, of course, the more time and effort you can expend on these MOOCs, the more benefits you'll receive. Naturally, you can also take these MOOCs solely to learn the material and expand your knowledge of Java and Android, in which case there's no need to take any quizzes or submit any programming assignment solutions at all. This MOOC specialization covers a wide range of topics, some of which require careful thinking and practice to master. To help you learn all this material, here are some strategies we suggest you consider when navigating through the lessons in these MOOCs. First, watch the lessons carefully before taking the quizzes and doing the programming assignments. Some topics we cover are technically deep, especially the more advanced Java features like inheritance and dynamic binding. So consider watching these videos multiple times, perhaps at different rates of speed, to fully comprehend the topics we're covering. Although we can't address all aspects of Java and Android in our limited time together, you may benefit from other online resources to learn more about these topics, either during or after these MOOCs. Therefore, many slides contain links to articles, tutorials, source code, and documentation that you can explore as your time and interest permits. No quiz questions relate to these supplemental materials, so feel free to examine them at your leisure. Although it's helpful to browse the freely available resources online, the list of suggested readings on the MOOCs GitHub website provides even more comprehensive information related to programming Java and Android. We therefore encourage you to read these books to gain additional insights into the material we cover in the lessons. We also recommend watching tutorials that provide additional coverage of topics related to Android and Java. For example, the videos and screencasts from the Coursera MOOCs and classes we teach at Vanderbilt University are a great online resource. Although MOOCs provide a flexible learning model, you may want a more immersive experience by attending Coursera Meetup groups near you, where you can join your fellow students for face-to-face conversations and further engage in the topics we cover. Another way to make this MOOC feel more like a face-to-face course is to participate in the online discussion forums, where you can interact with other students, post questions, give answers, clarify points of confusion, and learn who else is wrestling with some of the same challenges that you are. The teaching staff regularly monitors the forums and provides tips and pointers to mentor you through the learning process. However, they're only a handful of us, but tens of thousands of you, so please read the policies on forum posting at this link and be respectful of fellow students and staff. Now that you've completed this lesson, you should understand the overall structure of the MOOC and the main topics covered in each module, recognize what's expected of you to learn the material presented in the upcoming lessons in order to complete the programming assignments and quizzes successfully, and know where to find more information on topics related to developing Android apps in Java. Much of this information is available in the FAC, so please read it carefully prior to watching the remaining lessons, since it provides useful insights and suggestions to help you master the material in this MOOC. Welcome to the first part of the next lesson in this module, which begins our overview of the Java Object Oriented Programming Language. Java was originally created by James Gosling and his colleagues at Sun Microsystems in the early 1990s. Dozens of object-oriented programming languages have been developed over the past six decades. Although these languages differ in various ways, they all support key object-oriented programming concepts, such as abstraction, inheritance, and polymorphism. After completing this part of the lesson, you'll know what these concepts generally mean in the context of object-oriented programming, understand specifically how the concept of abstraction relates to the Java programming language, recognize the benefits abstraction provides developers of Java apps and Android, and be able to identify Java features that implement various data and control abstractions, such as Java's conditional statements, loops, classes, and interfaces. Neither parts of this lesson examine Java code examples in detail, since our goal here is just to provide the big picture of object-oriented concepts and Java features rather than give a detailed explanation of these topics, which is the focus of the rest of this MOOC. Therefore, feel free to race through this material quickly if you don't need a high-level overview of object-oriented programming concepts now, and then return later and re-watch this lesson after completing the remaining modules on the Java programming language. However, if you're interested in deepening your understanding of these object-oriented programming concepts at this point, we highly recommend that you read the material at the URLs listed on the slides to learn more about each topic we discuss. Java is an object-oriented programming language, which means that apps written in Java are organized in terms of structural elements, such as groups of classes, interfaces, and packages whose arrangements are guided by design patterns. These structural elements are used to create, access, and manipulate objects, which are instances of classes that perform certain operations and interact with other objects in and out. An object in Java resides in a memory location of a computer. It consists of state, represented by a Java data fields, and behavior, represented by a Java methods. Objects often correspond to entities found in the real world. For example, an online banking app might have objects like accounts. An account state keeps track of the account balance and whether overdraft protection is enabled. Likewise, its methods implement behaviors involving deposits, withdrawals, and checking the current balance of an account. In contrast, non-object-oriented programming languages, such as procedural languages like C, AIDA, or Fortran, organize apps in terms of functional elements, such as actions and logic. Naturally, object-oriented programs written in Java also perform actions and contain logic. However, these functional elements don't constitute the main focus of the way programs are structured and designed in Java. Instead, Java supports key concepts found in all object-oriented programming languages, including various data and control abstractions, such as classes and loops. These abstractions enhance the modularity and clarity of object-oriented app software by emphasizing important interfaces and operations and objects, and shielding app developers from unimportant implementation details that are likely to change over time. Other key object-oriented concepts supported by Java include inheritance, which enhances reusability by enabling a class to receive and extend methods and fields like transparent class and polymorphism, which enhances extensibility by enabling transparent customization of existing class behavior to meet new requirements. Many popular programming languages implementing these object-oriented concepts are in widespread use today, particularly Java, C++, C-sharp, and Python. Therefore, once you understand the features of Java covered in this MOOC, you should be able to learn other object-oriented programming languages quickly and easily. In Java, however, you may be bored by some portions of this MOOC. In this case, feel free to move through this material quickly, so you can start on the next MOOC in this specialization. However, make sure you really understand how to program Java for Android, since examples and assignments appearing later in this specialization assume you possess this knowledge. The first object-oriented concept supported by Java that we cover in this lesson is abstraction, which is an essential part of all object-oriented programming languages. Abstraction helps developers master the complexities of writing apps by emphasizing what's important and de-emphasizing what's unimportant at a particular level of detail. In particular, abstraction helps developers focus on what their apps are doing to meet the requirements rather than being distracted by lower-level implementation details of how their apps work in a given operating environment. Java supports many object-oriented abstractions that we cover throughout this MOOC. For example, it supports various data abstractions, such as classes and interfaces, which cleanly separate key abstract properties of a data type, such as its application programming interface, or API, from concrete implementation details, such as the use of a particular algorithm or data structure. This separation of concerns avoids breaking app code that uses the API when implementation details are modified or optimized. Java also supports a number of control abstractions, such as if statements and for loops, which determine the order in which individual statements or method calls are evaluated or run. We'll now summarize various examples of data and control abstractions supported by Java. Java supports data abstraction via the concept of an abstract data type, or ADT, which defines a set of data values and a set of operations on these values. For example, the Java integer class is an example of an ADT that contains a value, such as the number 42, together with operations on the value, such as methods that create an integer object from a primitive int value and vice versa, as well as methods that compare two integers for equality. At the heart of an object-oriented language's support for data abstraction is encapsulation, which hides an ADT's internal representation to ensure apps using the ADT can only access its public operations and can't access any of its implementation details that may change over time. Java supports ADT's via its class feature, which defines a blueprint for creating objects. A class provides both fields, which are used to store the state of an object, and methods, which are used to implement the behaviors of an object. For example, the Java string class contains fields that store a sequence of characters and a length of the sequence, along with methods that examine individual characters of the sequence, compare strings, search strings, extract substrings, and create copies of a string. In Java, all objects created from the same class share the same methods, but each object may store different data values in its fields. Another form of data abstraction supported by Java is the interface, which defines a contract specifying methods that classes implementing the interface must provide. A Java interface provides a subset of the features provided by a Java class. For example, an interface in Android cannot contain method implementations, only method signatures, which include the method name, and any parameters that indicate what values can be passed to a method when it's invoked at runtime. A Java interface can't be instantiated, but instead must be implemented by a class, which defines the interface's methods, along with any fields needed to implement these methods. For example, the Java comparable interface defines the compare-to method, that compares an object to another object to determine their relative order. This interface is implemented by classes like integer and string to define a natural order of their instances. Classes and interfaces can be grouped together into packages, which provide a namespace for organizing Java code in a logical manner. For example, the Java.lang package contains classes that are fundamental to the design of the Java programming language. The Java.util package contains a collection of common reusable ADTs, such as ArrayList, HashMap, and Vector. And the Java.io package contains a group of classes that perform system input and output via data streams, serialization, and the file system. Organizing classes and interfaces into packages makes it easier to manage large software projects with many team members by avoiding collisions between classes and interfaces that have the same common name, such as point, shape, or map. In addition to being grouped into packages, classes and interfaces can also be parameterized via the Java generics feature, which enables the passing of ADTs as parameters to the definition of classes, interfaces, and methods. For example, the Vector class in the Java.util package can be parameterized so that its methods operate on a particular ADT element, such as an integer or employee. Generics offer several benefits to Java programmers. For example, they eliminate the duplication of code by adhering to the Don't Repeat Yourself principle, which states that every piece of knowledge must have a single, unambiguous, authoritative representation within a system. Generics also ensure compiler type safety when operating on different types of ADTs. For example, a vector of integers will not accept a value of type double. Likewise, a vector of doubles will not accept a value of type integer. The Java collections framework uses generic classes and interfaces to implement common type-safe reusable ADT collections, such as ArrayList, Vector, and HashMap, which in turn can be parameterized by other ADTs, such as an ArrayList of integers, a vector of doubles, or a HashMap of employees. The Java garbage collector supports yet another form of data abstraction. Garbage collection is a memory management mechanism that automatically reclaims and recycles objects, not currently in use by an app. Java's garbage collector makes it easier to write apps by alleviating many tedious and error-prone aspects of releasing dynamically allocated memory in languages like C that lack garbage collection. For example, it abstracts the steps associated with manually keeping track of how long each object is used in an app so the object's memory can be released when it's no longer needed. Not all object-oriented languages support garbage collection, but it's an essential feature of Java. In addition to the data abstraction mechanisms we just covered, Java supports various control abstractions, which determine the order in which individual statements or method calls are evaluated or run. A fundamental type of control abstraction is the conditional statement, which can be used to selectively alter the flow of control through an app, so it performs different computations or actions, depending on whether or not a programmer-specified condition evaluates the true or false. An example of a conditional statement supported by Java is the if-else statement, which helps apps achieve flexible flows of control through their algorithms and data structures. Another type of control abstraction supported by Java is iteration, which enables the repetition of a block containing one or more statements within an app. Examples of iteration features supported by Java include for loops, while loops, and do-while loops. These iteration features are often combined with conditional statements to write Java apps with sophisticated control flows. Yet another form of flow control abstraction supported by Java is exception handling, which separates the control flow paths of normal app execution from the control flow paths of anomalous app execution. For example, by using exception handling, the control flow path of an app will differ in a nicely structured way if the file it attempts to open is available on the computer versus not being found. When used properly, exception handling makes Java apps more robust and easier to understand and evolve. Now that you've completed the first part of this lesson, you should know what the concepts of abstraction, inheritance, and polymorphism generally mean in the context of object-oriented programming understand specifically how the concept of abstraction relates to the Java programming language, recognize the benefits abstraction provides developers of Java apps and Android, and be able to identify Java features that implement various data and control abstractions, such as Java's conditional statements, loops, classes, and interfaces. The next part of this lesson provides further coverage of inheritance and polymorphism, which are more advanced object-oriented concepts supported by Java. Welcome to the second part of the lesson, which continues our overview of the Java object-oriented programming language. Most programming languages support a range of data and control abstractions, which make it easier to simplify the development of robust apps that are able to evolve flexibly over time. However, object-oriented languages go above and beyond data and control abstractions. In particular, Java supports more advanced object-oriented concepts, including inheritance, which enhances code reuse by allowing a class to receive methods and fields defined by another class, and polymorphism, which enables transparent customization of the methods inherited from an existing class. After completing this part of the lesson, you'll understand what these advanced object-oriented concepts mean, know the benefits they provide developers of Java apps and Android, and be able to identify Java features that implement these concepts. Although these advanced object-oriented concepts and Java features are powerful, they may take some time to understand fully. Subsequent lessons in this MOOC therefore examine Java inheritance and polymorphism in much greater detail, so you'll learn how to program these features effectively. Object-oriented programming languages enhance reuse by allowing classes to inherit commonly used state and behavior from other classes. Inheritance in Java is specified via its extends keyword. When a class, called a subclass, extends another class, called a superclass, the subclass automatically inherits all non-private fields and methods defined in the superclass. Private fields and methods are not visible to the subclass. For example, class B is a subclass that inherits mField 1 and method foo from the class A superclass. Apps that use instances of class B can therefore invoke both the method foo inherited from class A and the method bar defined by class B. This lesson uses the Java collections framework as a case study to demonstrate the capabilities and benefits of inheritance, which enables the reuse of existing Java software components. This framework defines a hierarchically organized set of classes and interfaces that implement commonly reusable collection data structures, such as lists and maps, which are covered later in this MOOC. Here we'll examine a portion of the list hierarchy, which are collections that implement the list interface and maintain an ordering for their elements. The Java Abstract Collection Superclass provides a skeletal implementation of the collection interface. This superclass forms the root of the hierarchy of collection subclasses that provide various implementations of ordered and unordered groups of abstract data type elements. Likewise, the Abstract List subclass extends abstract collection and skeletal implementation of the list interface, thereby minimizing the effort required to implement this interface using a random access data store, such as an array. Various concrete subclasses, such as Vector and ArrayList in the Java Util package, extend Abstract List to provide implementations of the list interface using dynamically resizable arrays. This inheritance hierarchy enhances systematic reuse of both data fields and methods for the subclasses of the Java collections framework. All Java classes directly or indirectly inherit from the Object Superclass that resides in the Java-Lang package. This superclass defines methods that can be used by all non-primitive types, such as classes and arrays. For example, Object defines methods that return an integer hash code for an object and use this hash code to check whether two objects are equal or not, as well as methods that objects can use for interactions and multi-threaded programs. Subclasses that don't explicitly extend a superclass implicitly inherit from Java-Lang Object. For example, the Java-Lang Process class doesn't explicitly extend any superclass, so the Java compiler implicitly inherits this subclass from Java-Lang Object. All instances of Java-Lang Process therefore also provide clients with access to the inherited Java-Lang Object methods. As you may have noticed, Java-Lang Object is the most general of all classes, since it serves as the root of the hierarchy of classes available to Java apps. Classes toward the bottom of this inheritance hierarchy provide more specialized behavior by overriding methods that are defined above them in the hierarchy. For example, the Vector, ArrayList, and LinkedList subclasses in the Java Util package implement their particular semantics by overriding certain methods higher up in the Java collections framework hierarchy. Subclass methods inherited from a superclass are generally used for three purposes. To make this discussion more concrete, we'll illustrate these purposes with an example of the generic stack subclass defined in the Java collections framework. This subclass extends the generic Vector superclass to define a last-in-first-out or LIFO data structure that enables apps to push and pop items to and from the stack, respectively. The first purpose for extending a superclass is to augment the methods defined in the subclass API. For example, the stack subclass inherits fields and methods from the Vector superclass. This code snippet shows how the isEmpty method inherited from Vector can be invoked on an instance of stack to determine if the stack is empty or not. The second purpose of inheritance is to use methods defined in the superclass to implement subclass methods. For example, the stacksPush method is implemented by the addElement method inherited from Vector, which is yet another example of systematic reuse that's enabled by inheritance. The third, and arguably the most important purpose of inheritance, is to override superclass methods in the subclass that have the same signatures. In Java, method signatures are considered the same if the method names are the same, and the number and types of method parameters are also the same. For example, the hashMap subclass in the Java collections framework overrides methods with the same signatures as abstractMap superclass methods, such as put and entrySet, which associate values with keys in a map and return a view of the mappings contained in a map, respectively. Method overriding enables a subclass like hashMap that transparently customize the behavior of a superclass like abstractMap, as we'll discuss next in our coverage of the Java polymorphism. This upcoming discussion will also explore the ways in which abstractMap methods can be overridden to define different mechanisms for associating values with keys in a map and returning a view of the mappings contained in a map. It's possible to apply inheritance in isolation to systematically reuse existing superclass methods and fields. In practice, however, inheritance is nearly always applied in conjunction with polymorphism, which is a key object-oriented concept that enables transparent customization of subclass methods inherited from a superclass. Polymorphism and inheritance are essential to achieving the benefits of the so-called open-closed principle in object-oriented design and programming, which states that a class should be open for extension but closed for modification. Installating a class implementation for modifications helps make the class more robust and flexible, since it can be extended and reused without introducing new bugs to existing code. In particular, the open-closed principle can be applied in conjunction with various patterns, such as factory method, which defines an interface for creating an object but leaves it to the implementation of that interface to decide which class to instantiate. In this case, the polymorphic methods of a class can be customized without modifying its existing source code or modifying the source code of apps that use instances of the class. Subclasses of a superclass designed in accordance with the open-closed principle can define custom behaviors that are more suitable for a particular use case while still reusing the structure and even some functionality provided by their parent superclasses. For example, vector and array lists are subclasses in the Java collections framework that inherit reusable methods from the abstract list superclass. However, the implementations of methods in the vector and array list subclasses emphasize different properties of a list, such as synchronized versus non-synchronized element access and different strategies for dynamically growing the underlying buffer when its size increases. Java apps apply polymorphism when a reference to a superclass is used to refer to an instance of a subclass. Methods in the subclass can selectively override methods with identical signatures defined in a superclass, thereby customizing their behavior to achieve the desired subclass semantics. For example, the abstract map class in the Java collections framework contains methods that can be overwritten by concrete subclasses, such as tree map, hash map, and concurrent hash map. In particular, the put and enter set methods in abstract map can be overwritten to define different mechanisms for associating values with keys in a map, and returning a view of the mappings contained in a map respectively. The subclasses of abstract map have different time and space tradeoffs that are appropriate for different apps in different circumstances. For example, hash map's implementation of put uses a hash function and an array of buckets to resolve collisions, which is suited for apps that want good performance in average and best cases. In contrast, tree map's implementation of put uses a balanced red-black tree data structure, which is suited for apps that want consistent performance even in the worst case. An app that invokes a put method call on a reference to an abstract map can be extended transparently by the open-close principle, so the appropriate put method implementation is dynamically dispatched at runtime based on the object type of the concrete subclass that extends the abstract map superclass, such as tree map, hash map, or concurrent hash map. By applying the factory method pattern together with the open-close principle, the app code needn't change, even if the make-tree factory method creates a different concrete subclass when it's called at runtime. Object-oriented programming concepts are at the heart of modern app development in mobile and cloud computing environments. Java has been one of the most popular object-oriented programming languages since its inception in the early 1990s, which is why Google selected it as the programming language of choice for developing Android apps. Now that you've completed both parts of this lesson, you should understand what key object-oriented concepts, like abstraction, inheritance, and polymorphism mean in the context of Java, know the benefits they provide developers of Java apps in Android, and be able to identify Java features that implement each of these concepts. However, don't worry if you don't fully understand all these object-oriented concepts and Java language features yet, since the remaining lessons in this MOOC examine each feature in greater depth, analyze detailed code walkthroughs, and reinforce the lessons with assignments that enhance your knowledge of programming Java for Android. There are also other excellent resources available online, including the official Java tutorials and the Android API documentation, so please leverage these online resources frequently as you progress through the MOOCs in this specialization. Now that you've completed the first module in our MOOC on Java for Android, you should be able to name the key object-oriented concepts and Java features needed to program Android apps, understand how to complete the course requirements, and the information and resources you need to succeed in this MOOC. Much of this information is available in the Frequently Asked Questions or FACC website, so please read it carefully prior to watching the lessons in this MOOC. If this MOOC inspires you to learn more about Android app development, please consider taking our mobile cloud computing with Android specialization, as well as watching the digital learning resources available at my website, which provide many more hours of lessons than object-oriented design and programming for Android apps, patterns and frameworks for concurrent and network software, and Android middleware and systems programming mechanisms. And now let's get on with the rest of our MOOC on Java for Android. Welcome to the second module in our MOOC on Java for Android, which presents an introduction to Android Studio and shows many examples of applying its tools and features to develop simple apps written using some basic Java and Android features covered in this MOOC. After completing the lessons within this module, you'll be able to install the Java Development Kit and the Android Studio Integrated Development environment. You'll also know how to create new app projects and import existing app projects into Android Studio, as well as know how to select and edit files that are commonly used windows and tools provided by Android Studio. Likewise, you'll learn how various types of files are organized and edited within Android Studio projects, including Gradle files to define how to compile and build an app, source code files that define the logic of your apps and resource files that control the apps look and feel. This module explains how to create and manage Android virtual machines. Which emulate the behavior of apps on your development machine so that they appear to run on physical Android devices. Finally, you'll learn how to use Android Studio's tools to help debug your apps and app projects. Additionally, the most effective way to learn the material is by opening Android Studio and following along with the examples in the lessons. In this video, we will show you how to install Android Studio on your computer. To start, open up your favorite browser and your favorite search engine, whatever they may be, and simply search for Android Studio Download. That's search for Android Studio Download. You will probably get the very first link will be to download Android Studio. You click on it and it will bring you to a page where you can download Android Studio. When you do that, you will always want to install and download the latest version. Currently, the current version is 4.0.1 at the time that this video is being made. Whatever time you're doing this, you always want to install the latest and greatest version of Android Studio. All you need to do is click on the download Android Studio button. You will get displayed their terms and conditions. Through them, if you'd like, click that you have read them and that you agreed to them and then click on download Android Studio. At this point time, the download will begin. Or your browser may ask you where you want to save. For me, my browser is already going to start downloading this software, the installer software to my computer and I can see this progress down here in the lower left. In the meantime, we're going to wait for this to finish and we're going to cut this portion of the video out and go right to the point where it's once it's completed. Now that our download has completed, we can click on this button over here and I can either open the software or actually I want to show it in this folder. I'm going to open it up in my download folder and I'm going to grab that executable and drag it on to my desktop. Once I've done this, I can close down the folder. I can close down my browser and then I can double click on the installer. It'll take a moment for the installer to open up and then usually your operating system will ask you if it's okay to have this installed so we're going to click yes and then the installer starts begins. At this point in time, we are just going to go through the installer and accept all the defaults. Please always accept all the defaults no matter what may be shown on the screen, just accept all the defaults. So here we want to install, yes, next. What components do we want to install? We're just going to accept the defaults. Next, where do we want to install it? We're going to install it in the default place. Next, what do we want to call it? We're going to call it the default, which is Android Studio. That's great. We're going to hit install. And now this installer will do the work to install Android Studio on your system. Again, we will edit this part out and you'll write to the point where the installation has been completed. Now that the installation is completed, we can just go ahead and click next. Then it says that it's been completed and do we want to start Android Studio? We're going to go ahead and start up Android Studio. Android Studio will then start up and you'll be displayed the open welcome splash screen, which is right here. Before we go in and do anything, the one thing we need to do is we need to make sure that we've loaded on your system the necessary SDK for the current version of this class. You need to have API 29 installed on your system. To do that, we just go to the configured drop-down menu down here and click that we want to go to the SDK manager. We want to click on that. The SDK manager will pop up and for me it shows that I already have API 29 installed. I also have API 22 installed. You can pick any API you want that's not necessary, but you're going to want to click that you want API 29 installed and then install it. I already have installed, so I go ahead and click OK. At this point in time, our Android Studio is ready to be used for this Coursera MOOC class. Our next video will show you how to open a project using Android Studio. In this little video, we are going to demonstrate how to get started on a program assignment. You first start by visiting the assignment page in Coursera. Here we are looking at the very first assignment on geometry calculations and you read through the introduction, the learning outcomes and the resources. Make sure you pay attention to all the information that's given to you that you can look at. You're going to want to read the project very carefully, but what we're interested in this demonstration is actually looking at the code. Under the supplied code is a zip file. You want to click on this zip file and download it to your computer. I have already downloaded it to my computer here. When we get down to these zip files, Android Studio does not operate on the zip file so you have to extract the contents of the zip file onto your computer. How you do that is based upon your operating system. For me, working on this Windows machine, I can just simply right click on it and specify extract all. I'm going to have this extracted to my desktop because that's where I have my current folder. I'm going to extract that file to my desktop and now we see that it shapes on my desktop. We can see right here, we click in it, we can see the application or the project. We're not interested in doing that. Now we're interested in opening this project in Android Studio. I'm going to bring up Android Studio and specify that I want to open an existing project. I always want to open an existing project. The project is provided for you. It's an existing project. We just simply want to open it. I'm going to click on open existing project. Then I need to find the project that I just created. For me, that's on my desktop. I need to expand my user ID. Go down to desktop. Expand desktop. Then we see here M3 shapes or whatever folder we just extracted. If I expand it, we will see inside of the app folder. We don't want to open up the app folder. We want to open up the folder that holds the app folder. M3 shapes, that is what we want to open up. We find this folder we just extracted and specify that we want to open it. I'm going to click on OK. Now this is where Android Studio needs to do a lot of work. Pay attention to all these messages down here on the lower bar. They're doing a lot of work and we have to wait until they are all done. Particularly this might take a while. The first time you open a project this is not the first time I've opened this project. This will be a little bit more quickly. Also pay attention to any messages down here about things being updated. Here I have enough things to say. My Android Gradle plugin is ready to be updated. I'm going to click on update. Always make sure your software is always updated. I'm going to go ahead and click update. I'm going to say update. This will take the time now to update the software here. This might take a while. It may not take very long at all. I see here that it's been updated. We can minimize that. At this point in time we now are ready to start working on the project. To do that we can click on to do to find out where the to do comments are. That's where we need to do our work. We see in here that they're in logic.java. We can double click on that. Here's our to do comments. This is where we need to work by adding our code. At this point in time you'll go back and refer to the project spec to find out all the things that you need to do. You'll add that code here at the to do comments. Again when you want to start working on a project you download the zip file you extract the contents of the zip file onto your computer. You then use Android Studio to specify that you want to open a project. You then select the file the project folder that you just extracted onto your computer and you open that so when you open and then you have to wait for all the progress messages to end. Once you do that then you can read the project spec and follow all the instructions to do your implementation for the assignment. That's all we're going to talk about in this video is how to open the project. In our next video we'll talk about after you've actually done your implementation how to test your project. We'll do that in the next video. Welcome to the next lesson in this module. Well you'll learn how to manage your projects within Android Studio. Android Studio allows you to not only create your own projects but also to import projects others have written. Therefore we'll show you how to create a brand new project using the new project wizard. This will allow you to create projects that you can practice and experiment on. Then we'll show you how to import an existing project into Android Studio. This will allow you to import the examples and assignments that we will give you in the future. After completing this lesson we'll understand how to create a new app project and how to import an existing app project into the Android Studio integrated development environment. When you have finished installing Android Studio you will have the following screen available to you. This screen allows you to both start new projects and to import existing projects. I will now show you how to create your own project with the built-in Android Studio. To start we click the top button here aptly labeled start a new Android Studio project. This will start the new project wizard. This wizard will guide you through creating a new project. The first step is to enter the name of the application you want to work on. By default it is my application. I will go ahead and alter that and it will ask you for your company domain name. This company domain does not have to be a real domain name. So we are going to go ahead and recommend you leave that as example.com for now. The project location is where on your file system your new project will be created. Adjust this as you see fit to easily track your files. I personally have a folder named in my user directory where I put my projects but this is up to you. Click next. This new screen will assist you in determining what kind of devices you wish your app to be able to run on. For now always pick phone and tablet and API level 21. We have chosen this API level so as to be able to teach you new features that aren't available in previous API versions. Click next. This next window will help you in creating the default user interface for your app. For simplicity's sake I will choose empty activity and recommend you do the same for now if you create any new projects on your own. Click next. The next window will allow you to change the names of some of the auto generated files that this wizard is about to create for you. I recommend leaving them as is for now and clicking finish. Android Studio will go ahead and go through the process of creating your new project for you. Once Android Studio's new project wizard has finished you will see the following window. The tip of the day will only show up until you click the show tips on startup button here. I recommend you leave this on for now and go through the tips and learn more about the Android Studio integrated development environment. For now we will go ahead and click close. And here you have your new project. After you extracted your project from a zip file you will want to go back to the Android Studio welcome screen. There you will want to click on the button labeled import project, eclipse ADT, Gradle, etc. Then a new window will pop up asking you to select the project you want to import. It is asking for the location on your file system where the project exists. There are helper buttons for your home folder and your desktop. So I will make use of the desktop button which is the second button up here at the top. Normally I would have put this project into my code directory but for simplicity of this example I am just making use of the desktop. Once you have found the location of your newly extracted project it may or may not have a green circular icon instead of the image of a folder. This is because I have already previously imported this project preparing for this video so my Android Studio knows that this folder is a Gradle project. You will want to select the folder of your project and click OK. Android Studio will use its automatic import wizards to auto-configure things for you and import the project. This may take some time or it may go quick depending on the complexity of the project you are importing and the speed of your machine. When it is done you will be able to view and edit the imported project just the same as if you had created the project yourself. Now that you have completed this lesson you should understand how to both create new projects and how to import existing projects within Android Studio. Welcome to the next lesson in this module where you will learn some of the major windows within Android Studio. Android Studio is comprised of a lot of tools and specialized editor windows that you will learn how to make use of. In particular this lesson will discuss the three most commonly used windows within Android Studio. The main editor window is where you will edit the source code files within your project. The project files window will show you the files within your current project and allow you to select and open files you want to edit. And the layout editor is where you will see the files that define what your apps use your interface look like and edit them. After completing this lesson you will understand what the main editor window the project window and the layout editor window look like and their function. Let us now take a tour of the Android Studio Integrated Development environment. The Android Studio IDE has a lot of features and tools available to us. We will only cover some of the most useful features. For example, the main window here is where you will view, create, and edit the files that will make up your project. The left hand side of the window is where you will have an overview of your project as a whole. But these windows are dynamic and movable. You can easily expand and shrink individual windows. Such as clicking on the project window right now it will open and close the project view for us. You can also drag and slide the windows once you put your cursor over the dividing line and two arrows appear. Then you can grab and pull in either direction. In the main editing window you can click the tab up here at the top and that will take you to the file that you want to view. In this example right now we are currently viewing the main activity.java. I'm going to click on the activity underscore main.xml. The main editor window here in the center is also where you will view your user interface layout files. Our automatically generated layout file activity underscore main.xml is what you are seeing right now. When we clicked on the new tab the visual representation of our user interface layout file was rendered for us to see. This editor right here is what is called a what you see is what you get editor. Meaning you can drag and drop a new user interface component onto the layout and it will appear how we place it. In this example I can grab a new button drag it onto the application, let go and a new button is applied to the user interface. However the layout files themselves are actually XML files. If you come down here to the bottom and click text it will show you the actual XML file that is creating the user interface that we were just looking at. Click back on design and you can see the rendered version of it. Now that you have completed this lesson you should understand how to navigate to and use these major windows within Android Studio. In particular where the main editor window is for editing source code files where the project view window is for viewing and selecting files and where the layout editor is for editing the apps user interface files. Welcome to the next lesson in this module. Where you'll learn how the files within an Android Studio project are organized. Android Studio projects have several different types of files that you'll have to learn how to interact with. The first set of files that we'll show you are Gradle files. Gradle files are the scripts that define how to compile and build your apps. We won't discuss these in much detail right now but we'll show you where they are for the time being. A second major group of files within the Android project are the source code files. These are the Java source code files that define the logic of your application. The third major group of files we'll show you are the resource files. The resource files are files that your app makes you sub while it is running. Such as the user interface layout files that define what different screens of your app look like. Any images that are included within your app including the app's icon itself and XML files containing values used by your app. One example XML file resource is called strings.xml. This file is where you put all the words displayed by your app. That way you can easily translate every word into a different language and easily swap in and out which language should be used based on the user's language settings. After you've completed this lesson, you should have an understanding of how the files within your project are organized, where to look for specific file types and how to edit those files. Now that we have a basic understanding of the Android Studio editors for both source code files and layout files let us take a look at how Android Studio organizes our projects for us. Within the project view window here on the left, we will see a hierarchy of folders and some files. I will now explain to you some of these folders and files so that you will understand where they are located. I will minimize or close the Java file right now and you will see that there exists two main sections of the project app and Gradle scripts Gradle scripts for now we will skip over these are not relevant to your assignments for this course. The app portion is where your projects files exist. There are three main categories of files in the Android Studio project. Manifests which are special XML files that describe how the Android platform should interact with your project. Java files which contain the source code and logic of our app and the resources folder abbreviated RES the resources folder contains things such as images, user interface layout files and other files that hold special values for us. Let us first examine briefly the manifest folder. The manifest folder will only contain a single file for your projects you work on for this course. That file is called androidmanifest.xml This file defines how the Android platform on each user's device will interact with our app but the specifics of this will be discussed later. The Java folder will contain two main groups of files. The first is the source code or logic files of your application The other is test files. These test files help us verify that our source code files are bug and error free. The test files are easily identifiable because of the android test here at the end. Within the main source code folder we have our main activity.java is what we are currently looking at right here. The .java is left out inside the project view but if you look at it up here you will see the .java is included within the file name. We will skip the test code for now but it goes inside this folder here. The resources folder or shortened to res is where we store our user interface layout files, images and other special files that our application makes use of. The layout files are in an aptly named folder called layout we only have a single layout file within our project right now so only that one is listed activity underscore main.xml This is the layout file we viewed previously. One of the most important special files in this section within the values folder. This file is called strings.xml This file is where the strings used within our app are stored as special xml values so they can be used easily throughout the rest of our project and when the app runs on a user's device. Now that you have completed this lesson you should understand how the files within a project are organized where to look for each type of file and how to edit source code and resource files. Welcome to the next lesson in this module where you'll learn how to edit the files within an Android project. Android Studio has two main sets of files that you will edit. Java source code files that contain the logic of your app and resource files such as the user interface layout files. There are a couple other types of files such as the Gradle build scripts which will very rarely be edited and which you won't be required to edit it all in this course. So we're going to focus in this lesson on how to create and edit Java source code files and resource files. As you progress learning how to develop for in the ant test okay. As you progress learning how to develop for the Android platform you will come to the point where you need to create your own Java classes. Java class is easy and is accomplished by right clicking on the Java package you wish to create your file in. So for example right clicking on this package then you go to the new menu option and click Java class. This will ask you the name of your new Java class. Java classes by convention have their first letter capitalized and then only capitalized the first letter of new words. So for example here is my custom logic class which only capitalizes the C and L. Click OK and you will create a new Java class file that you can work with. Creating a new resource file is easy and is accomplished by right clicking in the folder you wish for the new file to be created in. The new resource file wizard will pop up and ask you for details about the kind of resource file you are trying to create. The window will ask slightly different things depending on which resource folder you right clicked on. If this new resource file that we are creating is a layout file for our custom logic class then we will right click on the layout folder click layout resource file and enter the name custom underscore logic dot xml Click OK A new resource file will be created for us. Resource files are named in all under case with underscores between each name so in our case custom underscore logic. Now you have a resource file that you can edit just as you would your previous resource files. Now that you have completed this lesson you should understand how to create open and edit both Java source code files and resource files. Welcome to the next lesson in this module where you will learn how to manage android virtual machines. Virtual machines or VMs allow you to run code on your development machine or inside a physical android device. One of the reasons this is useful is for testing run time behavior of your app when you don't have a physical device to test your code on or the physical device or devices you have aren't of the exact same specifications as to what you want to test your code on. This could mean having a different slide screen having a physical keyboard or not or testing a different version of the android api. Therefore, in this lesson we will show you how to do four things manage your current virtual machines how to create a new virtual machine how to start a virtual machine and how to run your app on a virtual machine. The first step in managing, creating or starting a virtual device running android is to open the android virtual device manager. To do that you will click this button here when you mouse over it will say AVD manager click that and this window will appear this is a list of all the virtual machines you have created on your machine once you have a virtual device set up and you want to start it all you have to do is click the green play button right here to launch the virtual machine however if your virtual machine doesn't launch for some reason or if you want to create a new virtual device then you will want to click on the button labeled create virtual device a new window will pop up asking you to select which pre-configured hardware configuration you wish to select we will be using the Nexus 5 for all of our examples and assignments so go ahead and select that and click next and you will see a list of system images that you have installed on your system my list is probably a bit longer than yours but that doesn't matter the important thing is to understand what you are looking at this grid of information contains two key columns the API level and the ABI these are the two central columns the API level is the API level of the image or Android operating system version that you want to run on your virtual device the ABI or application binary interface is the specification of what kind of CPU architecture your virtual device will emulate the important thing to know from this is that the ARM EA BI version 7 is the most universal but it will run slower on our machines because it isn't of the same instruction set as our desktops or laptops therefore running an x86 or an x8664 image would be faster however your device meaning your laptop or desktop needs to have a CPU that allows for virtualization and needs to have a feature turned on I won't go into how to do this now because each CPU and each system is different and you will have to address this yourself therefore my recommendation is to use the ARM EA BI version 7 ABI with level 22 API if you do not have that listed in your window here then click the show downloadable system images check box here and you will see a list of system images that you can download on your system note that there will be two system images that contain both the ARM ABI and level 22 API you will want to download the system image that contains with google APIs once you have this downloaded and then selected click next this last window will display additional features that you can change but for now I will recommend not changing anything and just clicking finish the wizard will create that virtual machine for you and to start it you will just click that green triangle play button located here this will launch the android virtual device for you once the progress bar for the starting has completed you can close the android virtual device manager the android virtual device will appear such as this you can move the window as you normally would any other window and we will wait for the android virtual device to finish booting the boot process is similar to a physical device so therefore we will just need to wait for the virtual device to finish booting once it's finished booting we can interact with it as we would a normal physical device this enables us to test our application on a virtual device now we will show you how to run an android app on a virtual machine and or a physical device the term emulator is interchangeable with the term virtual machine in this context therefore I will use that now since it is what the on screen dialogues that you will see in a few moments will mention the phrase starting your app will also sometimes be called launching your app both are also fine to start with let us take a freshly created project that was just auto generated by the new project wizard in addition which window or windows you have open with an android studio and what you have selected generally doesn't matter when you attempt to launch your app there are some advanced topics which will impact this but we will cover those in the future when they become important for now the important thing to know is that all you have to do to start running your app on a device be it physical or an emulated one is to press the run app button this is a green triangle that looks like a play button this button is within the tool bar at the top of android studio you can see a zoomed in representation of this within the red highlighted box pressing the green button will tell android studio that you wish to run your app I will press it now each time you reopen an android studio project the following window will appear when you press the run play button for the first time this window is asking you how you would like to run your app there are main options you can choose to run on a currently running device or you can launch an emulator when making use of an emulator I always try to launch the emulator just after opening android studio this way it has had time to fully start up before I actually need it when you have an emulator currently running or you have a physical device connected to your development machine this is the first section of this window android studio allows you to have multiple emulators started at once that is if your hardware can physically support it and it allows you to have multiple physical devices connected at once also however when you would have multiple devices connected you need a mechanism to determine which device to direct your app to for it to run on the first section here in the window lists all currently connected emulators and physical devices I currently only have a single emulator running on my development machine if you don't already have an emulator running or if you want to start a new one you can do so by clicking on the second radio button labeled launch emulator there is a drop down box in this section that allows you to select previously configured emulators or you can press the button after it that will open up the android virtual device manager which we used earlier this allows you to edit or create a new emulator if you choose so I'll go ahead and close this window and go back to the device chooser window I'll click on the radio button labeled choose a running device and the emulator I currently have running will be selected as is the only option available if there were more devices currently running you could choose between them if you only have a single device be it an emulator or physical device that you are testing your app on right now then you can click the check box labeled use same device for future launches this will result in future presses of the green run app button skipping this device chooser window and automatically launching your app on the device you have chosen I will go ahead and uncheck this box for now and click ok to tell android studio to first build my app then to copy my app file over to the device and then to launch the app on the device I'll press ok now you'll notice that a new window has appeared at the bottom of android studio this new window is called the android monitor it allows us to monitor the device that our app is currently running on you can easily open and close the android monitor window by clicking in the tab below labeled android monitor the android monitor shows us information about the device that we are connected to such as memory cpu gpu and network usage it also shows us the log tab which is where the logs of both the system and apps are displayed this log cat tab in particular will be very useful later when you are trying to analyze your app's runtime behavior however this topic is beyond the scope of this lesson and will be discussed later in greater detail I will now switch to the emulator that I have had running in the background and show you that our app is now running on it our app doesn't yet have any logic in it so pressing the button won't do anything but we have successfully launched our app onto an emulator launching an app onto a physical device is the same process you just have to choose it from the list in the device chooser window when it appears now that you have completed this lesson you should understand how to manage your current vms how to create a new vm how to start a vm and how to run your app welcome to the next lesson in this module where you will learn how to use some of android studio's tools to help you debug your projects debugging refers to finding defects or bugs in your programs the term bug is credited to admiral grace hopper when in the 1940s she found a moth stuck inside a computer that she was working on at harvard for the us navy this bug created an electrical short and caused the program that the computer was running to fail she debugged the computer and got it working again hence the term became applied to computing when it comes to finding and resolving problems modern integrated development environment such as android studio come pre-packaged with advanced tools to assist you in finding and resolving bugs bugs and software can be categorized into two main groups logical and syntax logical errors are when your program runs and doesn't crash but instead it produces output which is incorrect fixing logical errors is something that requires practice and the experience of the developer to resolve the other type of bug is called syntax error syntax is the rules by which the programming language requires your program source code to be written for it to be a valid program syntax errors can cause your program to not compile which is called a compile time error or if it does happen to compile there can be advanced bugs that make it crash these bugs are called runtime errors since you only find them when you try to run your app both of these types of syntax errors or bugs can be caused by a lot of reasons ranging from the code missing some type of keyword a character in the source code files being in the wrong place perhaps a simple typo or more complex topics which we will discuss later in this course in this video we'll discuss some of the tools available to you in android studio that will help you try and resolve syntax errors while programming you will encounter times when your program syntax isn't correct syntax is the rules by which a programming language is required to be written for it to function when your program has syntax errors it won't be able to be compiled or tested I have a simple example program in front of us right now this file has no syntax errors but to create one all I have to do is delete this semicolon right here when I do this several things will happen now you will notice a red squiggly line where the semicolon used to be this is indicating that there is an error here you will also notice that in the left hand window showing the project that the main activity file the file that I'm currently working on has a red squiggly line underneath of it informing me at a high level that this file has a syntax error also on the right hand side of the scroll bar in the text editor window there is a red line that I can click on because the syntax error in my code is simple the editor gives me a hint as to what it thinks this problem is informing me that a semicolon is likely missing the editor doesn't always give a proposed solution for you nor is it always correct when it does make a suggestion but its suggestion is a good starting place for what might be causing problems for you if you click on the red line the editor will take you to the location of the error adding back in the semicolon removes the red warning lines from within the file from the project description and from the right hand side and indicates that the application is now back in proper syntax the first step in fixing bugs in your app is to first identify and locate them now that you've completed this lesson you should understand how to identify find and even how to read the suggested tool tips about syntax errors within your app hello and welcome to the next video in this lesson about debugging tools in this video we're going to introduce you to the concepts of logging and in particular logging with android's log cat first of all what is logging? logging is the process by which you create a log file obviously this leads to the question of what is a log file and it is a record of events that happen on a system specifically in android it is a record of system messages that both the android platform and the apps create while they are running these system messages can be a variety of things ranging from error messages notifications and even messages that a developer can write to help them examine their apps run time behavior as a developer you'll also be able to write these messages you just need to learn the specific statements to put in your source code additionally android studio comes with special tools to help you efficiently read and filter these messages therefore in this video we'll introduce you to the statements that you'll need to use to write log messages we'll discuss what log levels are and how they impact logging we'll go over how to read the log file and how to filter the output of the log and we'll discuss some good practices for you to use when writing your own custom log messages to demonstrate how to log your apps run time behavior I have written a simple application that does nothing other than display some text when the on screen button is pressed I will show you some simple source code that will demonstrate how to log information from your app while it is running first we must include the following line at the top of our class file with the other import statements this line will be explaining how to fill in another lesson but for now we include it to tell the source code which library or set of code to actually use for the log statements used below before we get to the log statements just mentioned let me first show to you and describe another line that is important this line which you can see now inside the red outlined zoom box is the local variable that identifies the class file from which the log statements will come from this is important later in larger projects that have multiple class files for two reasons because it allows you to quickly identify where a log statement came from and because it allows you to filter out log statements that don't come from a particular class file if that is what you want both of these really help the process of debugging run time behavior easier and faster now let us scroll down to where the log statements are you will see a method called button pressed this method is ran when the onscreen button is pressed therefore we have log statements at the very beginning and end of the method that will log when the method starts and stops additionally the log statement after the onscreen text view has its text changed now let us examine one of the log statements in more detail we'll first look at the one at the beginning of the method you can see this easier in the red outlined zoom box this statement starts with log has a dot i which I'll explain in a minute then has in parentheses two strings the first is log tag which references the string above that says which class the log came from and the second which is in green is the output which we wish to be in the log now let us examine the second log statement this one is similar to the first but you'll notice some differences the first being that after the log in the very beginning of the statement you will see a dot v where in the other statement it was dot i this indicates which log level the statement should be associated with android has six log levels assert error warn info the first letter of these words are used to indicate what level you want your log statement there does so dot i is an info level log statement and dot v is a verbose level log statement log statements exist in many programming languages and help the programmer to declare what the severity of an individual log statement should be this also helps in allowing developers to temporarily filter out statements that they don't deem significant at a current time when they are looking at logs by the log statements having a priority to their severity levels the log level assert has the highest severity meaning that if you filter on the assert level no other logs will be displayed that are below the assert level error has the next level of severity meaning that if you filter on error messages you will only see messages above or at that severity level meaning either assert or error this pattern continues with warning showing warning and the two higher severity levels error and assert with info displaying info statements and the three levels above it error, assert and warning then debug filtering shows debug and the previous levels and verbose has the lowest level severity meaning that if you filter on that level you will see all log statements getting back to the log statement we were previously examining it has the log tag variable as its first string which indicates it is from this class then it has a string in green similar to the previous log statement however after that green text it has a plus sign then the string value variable this will include the value stored in string value into our log statement this is how you log values of variables which is very useful when examining your app when trying to fix some kind of logical error in your source code that is producing incorrect output being able to look at a sequential log of log statements and the values that variables stored in time helps you build a better mental image of the runtime behavior of your app now let us run the app and examine how you do the filtering I was mentioning previously I have an emulator running in the background and I will launch the app on that emulator this will open up the android monitor window and display the log cat tab which is what we want we will click and drag this window up to give some more screen space for it to use now I will bring the emulator to the front and it is currently running I will press the button and the text will change we will go back to android studio editor and look at the log cat window you will see that new lines appeared in the log cat editor these relate to the log cat statements within our application if we look at the top and towards the center of the android monitor we will see what the current log level is set to for the filter currently it is set to verbose this means that all log statements are being shown this statement right here has a V at the beginning of it indicating that it is a verbose statement so if we select debug in the filter selection that statement will disappear the same is also true if we select info then the debug statements will disappear this pattern continues if we select warning then only warning and above are shown if we select error then no statements are shown because there are no error statements the last thing we will discuss in this video is the search bar next to the log level this allows you to search for particular text strings in log statements this is useful when you know what log statement in particular you are looking for the value of and can then search for that as an example let us enter the word changed and we will only show the log statement showing the value that the text was changed to you can narrow the search down to a particular class by entering that file's name if its log tag is set to the class name so for example main activity you can easily find all the main activity log statements that way I will now go back to the emulator and click the button a couple of times to show you another property of viewing logs within logcat that you should be made aware of you will now notice that all the logs are in order and that there is no clear separation visually between different button presses and for that matter the same would be true for you running your app multiple times the logs would just run together visually which is why it is a good idea to put log statements in the beginning of key methods so that you can identify when new executions of that part of your application have started so for example when you put in button pressed called indicating that a new button press started then hi and now that you have completed this video you should understand how log statements are written and how to write your own you should understand what log levels are and the impact they have on filtering you should be able to use logcat to read the log from a device and even how to filter the output and you should understand how the practices of consistent logging especially the beginning of key parts of your app can help make reading logs easier and more efficient welcome to the next video in this lesson where you will learn how to use a special set of comments called to do statements to do statements also called to do comments exist to help a programmer create a list of tasks that require additional attention this is useful in maintaining projects especially when the project size grows beyond a small simple app or when multiple people are working on the same project these to do comments exist to allow developers to leave easily traceable and findable comments within the source code that indicate further action is required in that location an example of this would be a developer leaving a message for themselves possibly others that they need to improve a section of code at some point in the future or check to see if there might be a more efficient way to accomplish what they have just wrote and have working in this course we will make use of to do comments within your assignments to indicate where you will need to complete the required code after completing this video you'll understand how to both use the special comments called to do statements to find the places within a program that require additional attention in future assignments we will make use of a feature of the android studio IDE called to do statements to do statements are comments that start with the word to do these comments are special because there is built in functionality into android studio that allows us to quickly find all the to do statements in our code to demonstrate this functionality I will create a to do comment here in the custom logic class then I will close this file and create a to do statement in the main activity class then I will close that file this example might seem simple because I only have two classes but if I had a project with hundreds of Java files it would be quite time consuming to search each file to see if it has a to do comment thankfully the IDE has a tool to help us at the bottom of the IDE there is a tab called to do if you click it it will list each to do statement within your project it will tell you how many to do items exist and in how many separate files in my case there are two to do statements in two files clicking the arrows will expand the view so that you can see more information the file name will be given and then each to do statement in that file will be listed the first number is on what line number the to do statement is so for example custom logic to do statement is on line number five if you double click a to do item listed here you can use this code file and take you to that to do statement it will do that for every to do statement you have listed here now I said line number and that can be important line numbers are used in lots of debugging methods within android studio and programming in general to view line numbers right click in the left hand window here of the editor and click on show line this I personally recommend you always leave it on now that you've completed this video you should understand how to enable line numbers within the editor and how to create to do comments along with how to use the to do window to quickly open and jump to existing to do statements visible line numbers along with to do statements will assist you in maintaining and improving the code within your projects these tools along with the tools from the previous video will by no means solve every bug you face while programming but they should help you to quickly identify and hopefully narrow down many potential bugs quicker and more efficiently in this video we are going to demonstrate how you can run your code to see that if it's working or not what we have provided we have provided three different ways for you to run and execute your code to verify that it works the first way is to actually run it in at the provided app to do that you would select app from the configuration drop down menu this menu right here just select app that you want to run the app next you need to select an AVD an android virtual device that can run on your machine this AVD needs to be running API 29 if you have not installed an AVD on your computer you can do so with the AVD manager again you can you should select any AVD that works on your machine you should probably select an ABI that is correct for your architecture particularly an x86 and for this course now you need to install API 29 so here I have some devices I have some API 22s and I have an API 29 device I actually have the API 29 device already running so here we can see my android virtual devices already running on my computer I started before this demonstration so we wouldn't have to wait for it to start up so again we select app we select our virtual device I already have my virtual device running and then we select the run button the run button will then compile your code and then install it onto the AVD for it to be run so we can click back over here to my AVD and we can see our app is now running on the android virtual device so here we see that we have input windows for a length, width, height and radius and we have a drop down menu here that we can select rectangle, box, circle, sphere or triangle so let's go ahead and select the rectangle since that was the default and we then press the process button and we see here the output that is produced by our code so a 10 by 10 rectangle has a perimeter of 40 and an area of 100 so we see that our perimeter method returned the value 40 and our area method returned the value 100 so it's similar we could select that we want to do the sphere and again press the process button again for now a radius 10 a sphere with a radius 10 has a volume of this value here 4 to 188 a sphere with a radius 10 has a surface area of this value a circle with a radius of 10 has a perimeter of this value and a circle with a radius 10 has an area of this value so we have and we can go in and we can change our values here let's go actually go in and change our radius from 10 to 150 and then press the process button we have to remove our keyboard and we can see the values for sphere volume, sphere area circle perimeter and circle area when our radius is 150 so we can actually go in and experiment and see if our values are getting if our code is producing the right values alright so that's one way to do it again here in android studio we select app we select an avd and then we press the run button another way that you can test your code is by running what we have what we call our unit tests these are tests that we have provided for you that actually do a very thorough job of testing your code to run the unit test we need to make sure that over here in the project when we're looking at the android view of the project so here again under this drop down menu you select that you want the project view or the packages view or the down at the bottom the android view we want to make sure that we select the android view for our project under that we have the app then under the app we have java under java we have two folders one is the shapes folder that's where our code actually is so we go under here we see logic and then logic.java there's our class that we are writing our code in okay this is at this file right here logic.java right here this file here is logic.java that we're editing right otherwise this other folder that says tests over here is our unit tests and all we do to run them all we have to do is right click on them we want to run the tests right click on the test folder we want to run the tests when we do that a run window will open up down here at the bottom and all the unit tests will be run so here we can see that expand this out we can see all these tests we can see this one failed we just got a green check mark now the green check mark just means that the test ran does not mean that the test ran successfully here at the test circle area it did not run correctly and it failed during its run right and that's because I introduced a bug in it so when we click on that one we can see over here that there was an assertion error while that test was running and that's because the test detected this value but my code actually produced this value and because of that that test stopped it had an exception and stopped so that's what that check mark excuse me not to check the X means the X means that this test did not run now the other test did run to completion but we don't know if they actually completed successfully or not to do that we need to scroll up here and check on the greater preview click on this and then we can take a look at here so this says our assignment has not been submitted our estimated score is 90 out of 100 again because in this case I introduced a slight error in my calculation of a circle area so my code is not correct for circle area and then we can scroll down here we see your solution received points for the following rubrics and we see oh hey our test of this circle circumference was correct we got 10 out of 10 testing of the box surface area was correct we got 10 out of 10 and we can keep scrolling down see all the tests that we passed and then down the bottom our solution missed points for these items ah test circle area we got 0 out of 10 right so there's a problem with our computation of a circle area again when I wrote that code I introduced a slight error again we can click on this test to get some information here hey this is the value that was expected and this is the value that I produced again they're not equal so again that is running the unit tests the third way that we have provided for you to test your code is with a gradle task to do that we need to come over here to the very far right and open up the gradle window click on the gradle over here on the far right under gradle window we have M3 shapes that's the assignment that we're working on the project we're working on underneath that there's tasks we'll open up that underneath that there's Coursera tools right so these are some tools that we have provided for you we're going to expand that and we will see that there are three tasks under here under the gradle Coursera tools the first one is grader preview all we need to do is double click on this and we will actually see what will happen when we submit our code to the auto grader on the Coursera servers so if we actually want to see what's going to happen when we submit our code for grading we just need to double click on grader preview so we double click on that we see down here on the bottom on the run window a lot of things are happening and then our test run in this window here you need to scroll up and scroll all the way up to the top and we see a bunch of messages of what's going on and then we see here hey there Simon's not been submitted this is just an estimate your estimated score is 90 out of 100 again we still have that error in calculating the circle area and then we again we see all the things we passed all the things we got right we see all those and we scroll down and again we see what we missed right and then we miss the computation of the circle area is incorrect again this is the feedback that you will get from the auto grader on the Coursera service the auto grader will not tell you what values were expected on what values you produced it will just tell you whether the things were right or wrong again if you want to know what was expected and what you got wrong you will need to run the unit test locally on your computer alright so there's again there's three ways that you can run the configuration drop down menu and select app and then select an android virtual device an avd and then hit the run button and actually run your code on an android device you can do the unit test right click on unit test over here and select that you want to run them or you can come over here to the grader window and specify under Coursera tools that you want to view the grader preview double click on that it will execute your code and give you the output that you will actually see or receive when you submit your code to the auto grader so three ways to run your test three ways of exercising your code and to see if your code is correct or not in this video we will show you how to submit your code for grading to the Coursera servers this is something that we've done some work to make this very easy for you so here we have an example of the first assignment that you will be completing we've run our unit test here we still fail the test circle area we haven't fixed our error yet but we want to submit anything anyway so up here under the gradle tab under the gradle tab Coursera tools M3 shapes, tasks, Coursera tools there is an option for submit for grading right and we will double click on this when we do that that will do a couple things it will actually execute this zip submission which will create a zip file for us that we need to submit and then this will also open up the webpage where you need to submit that zip file so let's do this, double click on submit for grading and we see a bunch of stuff going on and boom, our browser pops up and takes us to the page where we need to submit this solution to so here we are we are doing the geometry calculations again and this is now where we see here in my submissions tab and at this point time we can create a submission we see down below here that I have prior submissions but now we go ahead and do a click create submission and then here this is where you would add if this is the first time you would add your file at this point time for me I have already submitted so I would have to do a replace file but now to find the file that you need to submit you will submit a zip file let's go back to android studio and find out where that zip file got created again when we do this submit for grading it automatically does this zip submission which creates the zip file for you to find that zip file we are going to go over here to the left and we are going to change our view from the android view to the project view so again from this drop down menu here I am going to select project and then we will see here that there is a great little app all these things and then there is a zip folder and then behind that zip folder is submission.zip this is the file that you will submit for grading and so there is different ways to do that we can actually drag and drop this file onto our browser to submit the file or we can click here and like if I say replace file I will go here and then I will find that file here is the submission zip file right here if you do it this way this will always take you back to the most recent it will assume that you want to resubmit something from what you have done before so you need to make sure that you are always submitting from the latest one so I recommend to go back to your desktop and then go into the right folder whether it is m3 shapes or m4 diamond whatever you want to go in there and then find the zip folder and then find your zip file that you want to submit so here it is going to replace the file we can select our zip file again once you do that once it is uploaded you have to hit the submit button so if you upload it it is not submitted until you hit the submit button so don't forget to hit that submit button once you do that they will do some work let's go ahead and submit after we hit submit it is going to make sure that we have done our own work so that we understand the honor code and that the work that we are submitting is our own and we are going to continue and then we will get this little message here that your submission is being graded and this page will update automatically when it happens while we are doing that we will take a look at this prior submission that I did again I got scored out of 90 out of 100 why did I get so I can show the greater output and the greater output here is here I passed all these tests right down here at the bottom I am still failing the test circle area because I still have that bug but again we can see our output we can see what grade we score we can see the greater output the greater output here doesn't give us as much information as running the unit tests in android studio so always make sure that you run the unit test in android studio first before you submit to the auto grader in android studio to submit you can just double click on submit for grading in the gradle task under coursera tools coursera tools submit for grading double click on that that will create the zip file for you and it will pop open the correct page where you want to submit that zip file and then again we can just come over here make sure we look at our project view we will see the zip file and then that is the zip file we want to drag and drop when we are done and we have already submitted our file we want to go back to our android view of our project we will also want to come over here if we want to run the app we have to select the app from the configuration drop down menu that will get us back to where we were prior to doing our submission but again when we are done with our code and we are ready to submit it to the auto grader so we actually get a grade again go to the gradle window the gradle pane here and under task coursera tools double click on submit for grading that will create the zip file for you it will create a new zip file for you and it will open up the web page to where you want to submit that zip file and it is that easy good luck welcome to the end of this module which covered a range of topics related to the android studio integrated development environment now that you have completed the lessons in this module you should know how to install both the java development kit and android studio you should also be able to create and import projects into android studio as well as have learned its major windows and tools and know how to use them likewise you should understand how the files within an android project are organized and how to create and edit them in addition you should know how to manage create and run android virtual devices as well as how to run your apps on them finally you should have learned some basic debugging techniques for both syntax and logical errors in your apps understanding the material covered by the lessons in this module will become more important to us through this MOOC and beyond in particular knowledge of android studio will provide the foundation for other MOOCs in this specialization as well as enhance your ever growing knowledge and experience in developing java for android apps welcome to our next module in our MOOC on java for android programming which begins our introduction to computer programming java programming language in particular since this MOOC does not have any prerequisites we expect learners will come from a wide variety of backgrounds there will be some learners in this MOOC who have no prior programming experience while other learners may already know java and simply want to learn about programming java for the android platform since some learners have no prior experience however the first several lessons of this module will start with the very basics of computer programming while later lessons focus specifically on the java programming language the topics covered in this module lay the foundation for all future modules of this MOOC after completing the lessons in this module you will recognize key programming concepts and terminology you will also be familiar with the concepts of data types variables, assignment tasks in addition, you will understand key aspects of printing, mathematical functions and string processing finally, you will know how to define your own methods that can be reused to perform work for your apps depending upon your prior programming experience some of the lessons in this module may be a review for you so feel free to move through it quickly if you already know this material welcome to the next lesson where we provide some background on the computing system components needed to employ the java programming language to develop android apps after completing this lesson you will be able to identify the main components of a computing system and differentiate hardware components from software components you will also recognize some basics of how the hardware works since that knowledge is necessary to understand how the software works which in turn is necessary for your apps finally, you will understand the purpose of high level programming languages and the role of the compiler and virtual machine in creating and executing java programs you can probably speed through this lesson if you have prior programming experience to start things off let's define what a computer is a computer regardless of whether it is a desktop computer or a mobile phone is a device which can execute a program or what we call an algorithm and an algorithm is simply a precise, unambiguous, step by step process for completing a task note that all three of those attributes are extremely important a computer which is a marvel of engineering is by itself a very stupid device it can only do what humans tell it to do and when we tell it to do something we have to do it in a very precise, unambiguous step by step manner I like to make the analogy that programming is like creating a recipe that we've never baked before we've all seen the TV sitcom where the little kids are in the kitchen attempting to cook something without any help from adults and when the recipe says to add two eggs the kids simply drop two whole eggs shells and all into the bowl programming a computer is similar as the computer cannot know what you intend rather it only does exactly what you say now a computer system is made up of hardware and software that you can see and touch where the software is all the programs that run on the hardware even though this class is about creating software knowing some of the basics of the hardware helps us to understand how some things work and why we must do some things in a specific way the main component of a computer system is the central processing unit or CPU this is the chip that forms the brains of the computer it has two main components which are the ALU which does all the mathematical and logic computations and the control unit that really directs what happens there is also the memory where the programs and data are stored there are different types of memory including RAM or random access memory ROM which is read only memory and high speed cache and then there are the input devices that allow users to put information into the computer and output devices and now the computer to provide information back to the user now the main RAM memory of the computer stores the program that is running in any data that is used by that program in current computing devices this memory is usually measured in gigabytes where a gigabyte is a billion bytes so then the next question is what is a byte after all well inside the computer all information is stored by electrical charges the charges can be present or absent or on or off and each of these charges is called a bit and for ease of discussion we say it is either a one or a zero since a single bit by itself can only represent two values one and zero we group them into sets of eight and call that a byte the computer is able to access byte size chunks of information in memory by an address every byte has a unique address now all information that we store in the computer, regardless of what it represents is encoded as ones and zeros and since a byte which is eight bits can only represent 256 different values we usually have to group bytes together so that they can represent even larger sets of values for example to represent an integer in the computer we usually group four bytes together which allows us to represent over four billion different values now that we've covered some of the basics of computer hardware let's consider computer software since that is the focus of this class again software is simply the set of instructions that we want the computer to execute everything that is running on the computer is considered software all the way from the operating system that controls how the computer operates down to the games that you play on the computer now when we create these sets of instructions for the computer to execute we cannot use English which is neither precise or unambiguous which are two of the required properties of algorithms that we discussed earlier so we need to create special languages and thus programming languages are invented a programming language allows us to specify our algorithm or what we want the computer to do in such a way that the computer can understand it and actually do it for Android programming we use the Java programming language now Java programming languages such as C++ Python and Ruby are considered high level languages since they are easy for humans to understand but unfortunately computers do not understand such languages since they only understand ones and zeros thus we need a way to transform a program written in a high level language down into the ones and zeros that the computer understands to do that we use a program that is known as a compiler the compiler takes your high level program known as the source code and converts it into object code or the ones and zeros that the computer understands this object code is platform specific and thus the object code created for a Windows machine will not run on a Mac or an Android device now Java is a bit different in that its compiler does not produce object code that only runs on a particular computer instead the Java compiler produces what is known as a byte code which is object code for a hypothetical computer or what we call a virtual machine this byte code is a low level code that can run on any computer that has a piece of software known as the Java virtual machine or JVM this allows the same byte code to be executed on any computer regardless of what operating system it is running this lesson gave you an overview of the components of a computing system and concepts of hardware and software now that you have completed this lesson you should be able to identify the main components of a computer system recognize the basics of how computer hardware and software works and understand the purpose of using a high level programming language to create apps as well as understand the role of the Java compiler and the Java virtual machine in creating and executing Java programs welcome to the next lesson in our module on basic Java features for developing Android apps which introduces you to the concept of variables and types after completing this lesson you will recognize the important role that variables play in computer programming you will also learn the rules for Java identifiers that we use to give names to various entities in our programs moreover you will understand the concept of the data type and why it is important for us to specify the types of values in our programs to give a new value to a variable as with the previous lesson you can probably speed through this lesson if you have prior programming experience in a language similar to Java to motivate this discussion let's first answer the question of why do we need variables let's say we want to create a calculator app it would be very easy to create an app that adds 2 plus 2 but users of a calculator app want to do more than just add 2 plus 2 they may also want to add 3 and 21 or maybe they want to perform subtraction instead of addition or multiplication or division such an app is doing the same thing performing a calculation between two numbers but the numbers and the type of calculation may vary thus our app needs things called variables to hold these things that may vary variables allow our program to store information such as numbers and letters and the information is stored in the computer's memory we call the stored information the variables value and the key property of a variable is that it can be given different values while the program is running every variable has two key attributes a name and a type we'll consider these one at a time starting with the name in Java an identifier is a name that we give to a variable we also use identifiers to give names to other things we will see later such as methods and classes Java requires that identifiers be constructed from a sequence of characters containing only letters digits and the underscore character and they cannot start with a digit these restrictions mean that you cannot use characters that are allowed in naming files on your computer such as the space character or a dot or a hyphen and Java identifiers are case sensitive and thus a lower case stuff and a capitalized stuff and an uppercase stuff are all different identifiers and Java allows you to create identifiers that contain as many characters as you want but some identifiers have special meaning to the Java language we call these reserved words and thus you are not allowed to use them as identifiers in your program we will make note of these reserved words as we encounter them as this class progresses we as Java programmers follow some conventions as we create the names in our programs these are just common conventions that are not hard and fast rules that the Java language enforces the first convention is that names given to variables and methods will begin with a lower case letter if the name contains multiple words we use capital letters to highlight the other words we call this camel case since there are humps in the middle of the identifier the next convention is that the names given to classes begin with a capital letter and finally, good style says that the names we use should be descriptive of what is being stored or performed so again a variable has a name and a type now that we know about names let's move on to types recall that everything in a computer is represented by a sequence of 1's and 0's and thus we need to tell the computer to have a sequence of 1's and 0's so that it knows that this sequence represents a number while this other sequence represents a word so a type defines how to interpret a sequence of 1's and 0's as data and also defines what operations are valid for that data value Java has several types that are called primitive types since they are built into the actual computer hardware there are four types that can be used to hold whole numbers we refer to as integer types most often we will simply use the type int then there are two types that can be used to hold floating point numbers of which we will most often use the type double there is one type for holding a single character and that is the type char you may hear people pronounce it as type care since it is short for character but I've always pronounced it as the type char and the last primitive type is boolean which can hold a single true false value any type that is not primitive type will be an object type and we will see those later here is a slide showing the different primitive types in Java and how many bytes are used to store them and what range of values they can represent as you can see the int type uses four bytes and can represent integer values from slightly lower than negative 2 billion to slightly higher than positive 2 billion and here are some examples of values of these different types integer values will always be whole numbers while floating point values will have fractional parts note that negative 22.0 is a floating point value since the presence of the decimal point tells the compiler to represent this number as a floating point value rather than an integer value and they have very different representations as a sequence of ones and zeros character values are always a single character and use a single quote mark around that character and finally boolean values are either true or false now that we know about names and types we can combine the two to declare variables to declare a variable you need to specify both the type and the name the type appears first and then you specify the name you want to give the variable in this case we are declaring that we want to have a variable named number of rings that will be if type int java requires that we declare a variable before we can use it and it is important to remember to use descriptive names since we want other programmers to be able to read and understand our programs more formally the syntax to declare variables is to specify the type desired and then follow the type with a comma separated list of identifiers that we want to have that type and the list is terminated with a semicolon here are some examples from the circus we see we have two variables number of rings in attendance whose purpose is fairly clear from their descriptive names since the number of rings in the circus and the number of people in attendance are whole numbers we have declared these variables to be if type int we also have variables to keep track of the diameter of the ring and the weight of the lion since those values may have fractional parts we have declared them to be if type double and finally we have a variable to keep track of whether the lion has been fed or not which might be very important information for the lion tamer it is declared to be type boolean since it has a simple yes no or true false value we learned earlier that a variable must be declared before it can be used there are two standard places where we declare variables we either declare a variable just before it is used the first time or we declare at the beginning of the section of code that uses it that is at the section of code enclosed in curly braces you will see plenty of examples as you go through the rest of this course now that we can declare variables we want to give them values to do that we use an assignment statement the assignment statement gives or assigns a new value to a variable for those of you who are familiar with the novel the hitchhiker's guide to the galaxy may understand why we are assigning the value 42 to the variable named answer in this context the equal sign is called the assignment operator and it has a different meaning than the equal sign that we use in algebra the syntax of the assignment statement places the variable on the left followed by the assignment operator and then finally an expression that produces the value you wish to assign to the variable we will learn more about expressions in a moment note that the variable to be given a new value is always on the left of the assignment operator the expression is on the right some simple examples include assigning the value 4 to the variable num of stacks or assigning the value of the character q to the variable top card or assigning the value 10 times the value of the cards played to the variable score note that in evaluating the assignment statement the expression on the right of the assignment operator is evaluated first to produce a value and then that value is assigned to the variable on the left of the assignment operator in this example we first evaluate the expression on the right by getting the current value of cards in hand which is the value 8 and then subtracting 1 from it this new value 7 is then assigned to change the variable card in hands this is an example that the equal sign does not mean mathematical equality as this statement does not make any sense in mathematics it can be used in expressions and it can be given new different values in this example we see that the variable x is assigned the value 3 is then used in several expressions and then is assigned a new value that it will hold until it is possibly changed again this lesson gave you an overview of variables and types now that you have completed this lesson you should recognize the important role of variables as well as learn the rules you must follow to understand what a variable is you should also understand what a data type is and know the primitive types that are built into the Java language finally you should know how to use an assignment statement to give a new value to a variable welcome to the next lesson in our module on basic Java features for developing Android apps which introduces you to the concept of Java expressions that can produce values after completing this lesson you will understand Java's arithmetic operators and its interesting behavior you will also know how some of Java's specialized assignment statements allow short hand notation for common assignment operations that occur frequently in practice finally you will learn the concept of type compatibility in Java and its relationship to assigning values to variables as well as recognize how type casting can allow you to selectively modify Java's default assignment behavior next we will explore the expressions on the right hand side of an assignment operation an expression is simply a value or operation that produces a value the simplest expression is a little value which simply produces it itself or complex expressions can be created using operators and parentheses just as in mathematics arithmetic expressions can be created using the standard set of mathematical operators for addition subtraction, multiplication, and division there is a fifth operator the percent sign that is the mod operator but before we discuss the mod operator let's briefly talk about the division operator now division works as one would expect if one of the operands is a floating point value and in that case you get a floating point result but when both operands are integers you get integer division which produces an integer result the integer result is truncated and not rounded so if you divide the integer 14 by the integer 4 the result is the integer 3 if you did not want integer division you would have to make one of the operands a floating point value and that could be accomplished by simply adding a point zero to the little value now the mod operator can be used to produce the remainder that occurs after integer division so when we divided 14 by 4 the answer was 3 but there was a remainder of 2 that was lost the mod operator allows us to get that remainder and thus 14 mod 4 produces the value 2 students new to programming often wonder what such an operator is good for but it is interesting just how many applications it has in computer programming it can be used to easily determine if an integer is even or odd we can determine that by doing mod division by 2 and seeing if the result is zero meaning that the number was even or 1 meaning that the number was odd when creating expressions you can use parentheses just as you do in mathematics to force a specific order of operations in the examples shown we can use parentheses to force the addition to occur before the multiplication or to force the multiplication to occur before the addition without parentheses we will use the standard rule of precedence to determine the order of operations in evaluating an expression the rule of precedence are similar to mathematics where our unary operations have highest precedence followed by the multiplicative operators which are then followed by our additive operators when binary operators have equal precedence they are evaluated left to right in this example we see that the leftmost addition will occur first followed by the subtraction operator and then finally the rightmost addition will occur last when unary operators have equal precedence they are evaluated right to left when the operands of an operator are mixed ints and doubles the result will be a double value the compiler will automatically convert the integer value into a floating point value so that floating point arithmetic will be used so if we multiply 4.2 by 3 the integer 3 is converted to a floating point 3.0 for the multiplication and the result is a floating point 12.6 now this conversion is done per operator affecting only its operands so given the displayed expression the first operation to be performed is the leftmost division operation since both of its operands are integer values we get integer division and the integer value 2 is produced the next operation to be performed is the multiplication since its operands are mixed the value 2 will be converted to 2.0 and the multiplication produces a value 2.4 the next operation is the rightmost division operation again since both of its operands its operands are integers, we get integer division and the result is the integer value 1. Finally, the addition is performed to produce the value 3.4. Because programmers perform certain operations again and again, Java provides several specialized assignment operations that ease the writing of code. In particular, Java allows the assignment operators to be combined with arithmetic operators so that it becomes easier to update a variable. For example, we often want to update a variable by adding or subtracting a value from the variable. In this example, we want to update the variable time by adding 10 to it. This can be done more compactly using the plus equal operator that performs addition and assignment in one step. This can be done with all five mathematical operators. Note that the expression on the right hand side of the specialized operator is fully evaluated before the specialized operator is performed. This is important if the expression on the right hand side has lower precedence operators than the specialized operator. Another common operation is to increment or decrement a variable by 1 and Java provides special operators for this. The plus plus operator is the increment operator and it will increase the value of a variable by 1. Similarly, the decrement operator is minus minus which decreases a variable by 1. These operators are easy to use and they are important to recognize when you read code written by others. So if you ever need to increment a variable, there are several ways to do so and you are free to choose any of them. One is not necessarily preferred over the other as in the end the same code will be executed. Similarly, there are several ways to decrement a variable and you can use anyone you wish. But before we move on, let's talk a bit more about the increment and decrement operators. Besides incrementing or decrementing a variable, these operators also return a value. In the case of pre-increment where the plus plus operator precedes the variable being incremented, not only is the variable incremented but the new value is returned as the result of the expression. In the case of post increment where the plus plus operator follows the variable being incremented, not only is the variable incremented but the original value of the variable is returned as a result of the expression. In most cases we are only using these operators to increment a variable and we ignore the return value in which case you can use either pre-increment or post increment. Returning to the topic of declaring variables, a variable is said to be uninitialized if it has been declared but not yet assigned a value. In Java, the compiler will not allow you to use a variable that has not been initialized. So it is good programming practice to give a variable a value when it is declared. This is called initialization since it gives the variable an initial value as soon as it is created. This is accomplished by combining variable declaration statements with assignment statements, though we call it initialization rather than assignment in this situation. For example we can declare a character variable grade and initialize it with a character A. When the compiler allocates space in the computer's memory for the variable grade, it will give it an initial value at the same time. The final concept that we are going to discuss in this talk is type compatibility. Java is a strongly typed language and thus it does not allow certain type of assignment statements if those assignment statements could potentially lose information. For example, Java will not allow you to assign a floating point value to a variable of type int since that variable cannot store the fractional part of the value and thus information would be lost. But Java does allow certain conversions. As such it is okay to assign an integer value to a variable of type double. In such a case the compiler will automatically convert the integer value into a floating point value since such a conversion will not lose information and then assign the converted floating point value to the variable of type double. This automatic conversion that is made by the compiler is called a coercion. So in Java you are allowed to assign a value of one type to a variable of another type as long as the type of the variable is further to the right in this chain of types. For example you can assign a variable of type short to a variable of type int or a value of type int to a variable of type double. But the compiler does not allow assignment to variables whose type is to the left of the value type. If you ever want to assign a value to a variable whose type is to the left you can only do so by using a type cast. A type cast will change the value from one type to another type even if that conversion may lose information. But you have to explicitly state that you want that conversion to happen. The way to specify a type cast is to specify the desired type inside parens in front of the value you want converted. In this example we have a floating point value 9.0 assigned to the double variable distance. If we want to assign this value to an integer variable points we must specify the type int inside parentheses. This will get the value of the variable distance, convert that value to an integer value and then assign the resulting integer value to the variable points. Note that this conversion is only performed on the value taken from the variable distance. It does not affect the variable distance. The variable distance is still a variable of type double and it still holds a value 9.0. And it is important to note that the conversion of a floating point value to an integer value is performed by truncation rather than rounding it. This lesson gave you an overview of Java expressions focusing on how we can use them to compute new values. Now that you have completed this lesson you should understand Java's arithmetic operators and their behavior. You should also know the shorthand notation of Java's specialized assignment statements and understand when and where to use them. Finally, you should have learned the concept of type compatibility and type casting which are important to understand when writing correct Java programs for Android. Welcome to our next lesson in our module on basic Java features for developing Android apps which introduces you to the concepts and Java capabilities needed to print data to the screen of your Android device. After completing this lesson you will know how data is displayed on the screen and how to use Java's various print statements. You will also learn about Java string literals that you can use to create messages to be printed. Finally, you will understand the concept of an escape character and how to use them to print special characters. As with some previous lessons you may be able to speed through this lesson if you have prior programming experience in a language similar to Java. In this quick lesson we are going to learn how to print data to the screen of an Android device using Java. Now Java defines a special object called system.out which corresponds to the console of a desktop computer and when you print something to the special object the information will appear on the computer screen. Everyone who learns the Java programming language on a desktop computer learns how to print data to system.out. Unfortunately, it is more complicated when it comes to print to the screen of an Android device. So for the purposes of this MOOC and for your programming assignments we have to find an object called out which will act like system.out. Thus anything you learn here can be transferred to Java programming of the desktop computer and any knowledge you already have from programming Java on a desktop computer will transfer to your work in this MOOC. So print you to the screen is as simple as calling the printlin method on the out object and specifying what you want to have printed. Then the out object will send data to a text box on the Android screen and the printlin method will print whatever you tell it to print. In the previous module of this MOOC in which you were introduced to Android studio you saw the Hello World program. Let's take another look at that example. Here is the Hello World code that you saw earlier. Since you will be provided much of this code for your earlier assignments in this MOOC we are going to ignore the declarations of the logic class and the process method. Rather let's simply look at the line that prints Hello World by calling the printlin method on the out object. And as you saw during the demo of Android Studio, Hello World will be displayed in a text box on your device's screen. So the printlin statement displays output on the screen or a text box associated with the out object. There are two ways to use the printlin statement. You can use it to display a specific message or you can use it to print a blank line. Next, let's look how we specify the words we want printed. We print what is known as a string, which is simply a sequence of characters. Formally, we call this a string literal. A string literal is delineated by double quotes. Everything between the double quotes is a part of the string. But the double quotes themselves are not. Here are two examples. Notice that a string can contain most but not all printable characters. There are a few restrictions to these string literals. Two important restrictions are that the string must appear all on a single line. And the string cannot contain the double quote character, since the double quote character is used to mark the start and the end of the string. But what if we actually wanted to print the double quote character as a part of the string being displayed? For example, we want to print the word Java inside double quotes. To do this, we must use what is known as an escape character to tell the compiler that these quote marks are a part of the string we want printed rather than marking the start or end of the string. The escape character is the backslash character, and it precedes the double quote characters that are a part of the string to be printed. Besides printing double quote characters, there are several other escape sequences that allow us to add special characters to our strings. Since the backslash character is our escape character, if you want to actually print a backslash character, it must be escaped by using two backslashes. The backslash t is the escape sequence for inserting a tab character into the string. And the backslash n is the escape sequence for inserting a new line character, which causes a following data to appear on the next line. Even though each escape sequence is two characters together, the compiler treats them as a single character. Let's consider this example. We have a prism statement that is printed in a string that contains several escape sequences. Take a moment to look at the string. Are you able to identify the escape sequences? Here is the same string where the escape sequences have been highlighted so that you can see them easier. And here is the output that is generated. When using the print line statement, it is very easy to print out the value of a variable along with some descriptive text. You only need to use the plus sign between the string and the variable name. As you see in these examples, we are performing some simple computations to give values to variables. And then we use the plus operator to combine the values of the variables with strings to be printed. And here is the output. Note that if you want spaces between the words printed and the values of the variables, you need to include those spaces as a part of your strings. In this context, the plus operator is not performing addition, but rather is performing string concatenation, combining two strings to create a new larger string. And when printing a variable, the value of the variable is converted into a string so that it can be concatenated with the surrounding strings. Thus, in this example, the value of the variable average, which is 47.5, is converted into a string so that it can be concatenated with the string that says the average was. Recall that the job of the print statement is to print an entire line to the screen such that whatever is printed next appears on the following line. There is also a print statement that will print data to the screen but without moving to the next line when done. This allows you to use several print statements to print data across a single line on the screen. Here's a simple example of using the print statement along with the print line statement. Note that when you use the print statement, the next print statement continues on the same line. Whereas when you use the print line statement, the next print statement continues on the following line. Then just as before, if you want spaces between your strings, you need to explicitly include them yourself. Notice how the first print statement does not include a space nor does a subsequent print line statement. And thus, there is no space in the output and the strings are abutted to one another. And finally, there is a printf statement that is useful for printing formatted text. To use printf, you need to supply what is known as a format string, which is followed by the values you want printed. The format string will contain placeholders to specify where the values will be printed and how to print them. You need to use different placeholders based upon the type of the value you are printing, percent D for integer values, percent F for floating point values, and percent S for string. Here's a simple example of printing the X and Y coordinates of a point in a nicely parenthesized way as we normally do in mathematics. The format string is printed as given, but with the placeholders replaced with their corresponding values. Placeholders can be specified with precision and field width information so that we can format the data exactly the way we want it. Using the field width specification can make it very easy for us to print data in nicely formatted columns that are either left or right justified. We are not going to take the time to discuss all the different formatting options that are available with the placeholders. Rather, we recommend that you perform the necessary web search when you are looking for special formatting options. This lesson introduced you to the concepts and Java capabilities related to printing data to the screen of an Android device. Now that you have completed this lesson, you should know Java's different print statements and how they work to display data on the screen. You should also have learned how to create string literals to create messages that can be displayed. Finally, you should understand the concept of escape characters and how to use them to add special characters to a string. Welcome to the next lesson in our module on basic Java features, where you will learn about Java's math class, which contains a large collection of common mathematical functions. After completing this lesson, you will understand the purpose of the math class and be familiar with many of its methods. You will also know how to call a method in this class and use the result in a larger mathematical expression. In addition, you will recognize key predefined constants in the math class. Finally, you will learn how to apply typecasting in conjunction with certain math methods when it is required by the Java language. In this lesson, we are going to learn about Java's math class and its available functions and how to use them. Recall from your high school trig class that the tangent of an angle was computed by dividing the sine of the angle by the cosine of the angle. Now, if we were to do similar computations in a Java program, we would want to save the results of the division operation in a variable. But for now, let's focus on the operands of the division operation. When we see sine of x, we understand that there exists some function sine that takes a parameter x, which represents the angle we are interested in. And the function called sine of x will return the value of the sine of that angle. Similarly, cosine of x will return to us the value of the cosine of the angle x. It is functions like these that we want to explore in this lesson. The Java language provides many useful predefined functions, which are grouped together in collections called classes. In particular, there is the math class that provides many of the standard math functions that we may want to use. In Java terminology, these functions are referred to as methods. And for the math class, all of these methods will return values back to us that we can then use as we wish. To use or call these methods, we need to specify the class name, which is math with a capital M, followed by a dot, which is followed by the name of the method. The parameters that we want the method to operate on are specified in parentheses, just like in mathematics. The math class and its methods are available to all Java programs. You do not need to do anything special in your code to indicate that you want to use them. Most of the math methods expect you to supply parameters on which you want them to operate. Again, these go inside the parentheses that follow the method name. If there are multiple parameters, you separate them with commas. You must always have the parentheses for the list of parameters, even if the method does not take any parameters. In that case, the parentheses are empty. And a key feature of all the methods of the math class is that they return a numeric value that you can use in some expression. Here are several examples. Calling math.square root will compute the square root of the parameter. Calling math.absoluteValue will compute, you guessed it, the absolute value. And calling math.min() will determine which of two values is the minimum or smaller value. Here are some of the more popular math methods. We see we can compute the absolute value. We can round a value to the nearest whole number. We can round a number up or down. We can compute the logarithm of number. And we can find the larger or smaller of two values. We can also compute the result of raising one value to the power of another. We can compute the square root and the standard trig functions sine, cosine, and tangent. Note that the trig functions expect the angle to be measured in radians rather than degrees. But luckily, there are methods that allow us to convert between degrees and radians. And there is a method that will return us a random floating point value in the range from 0 to 1. Note that this is an example of a method call with no parameters. The math class has many more methods than the ones presented here. Perform an appropriate web search for a complete list. The math class also has two predefined constants. E, which holds Euler's number that is often used in calculating compound interest and other calculations. And the constant pi that we use in geometry and trigonometry. To access these constants, you must use the dot notation with the class named math. Before we end this lesson, let's take a closer look at the methods that round floating point values. The round method will of course round a floating point value to the nearest whole number. The interesting thing about this method is that if the parameter is typed double, then the result is a type long. Now the floor method returns the largest whole number that is smaller than the parameter, i.e. it always rounds down. While the seal method, short for sealing, returns the smallest whole number larger than the parameter, i.e. it always rounds up. These two functions, when given a parameter of type double, will return a value of type double. So these three methods always return whole numbers, which we may likely want to assign two variables of type int. But we learned earlier that Java's type compatibility rules will not allow us to directly assign values of type double or long to a variable of type int. Rather, such values must be cast prior to being assigned to an integer variable. This lesson presented an overview of Java's math class, which contains a large collection of common mathematical functions. Now that you have completed this lesson, you should understand the role of the math class and be familiar with many of its methods. You should also know how to call a method of the math class and how to use the result. In addition, you should recognize key constants provided in the math class. Finally, you should have learned how to apply type casting in conjunction with certain math methods when required by the Java language. Welcome to the next lesson in our module on basic Java features, where you will learn about Java string class, which you can use to create and manipulate string objects. After completing this lesson, you will understand the purpose of the string class and know how to create string objects. You will also recognize some of the most common string methods and know how to call methods on a string object. In addition, you will be able to identify the differences between a string and a character. Finally, you will know the role the character class plays in Java programs. In this lesson, we are going to learn about Java string class. Now, Java string class is very different than the math class we saw in the last lecture. The math class simply was a collection of functions, but the string class represents a whole new data type that we can use in our programs. Up to this point, we have seen that we can have variables, which allow us to store data in our programs, and we can have methods or functions, which can produce results or do things for us. Now we are going to learn that it is possible for these two concepts to be combined to create new data types. These new data types will have values associated with them, and also prepackaged methods that can process those values for us. We will label these types as object types and refer to variables of these types as objects. Initially, we will learn about some of the object types built into the Java language, and in a later module, we will learn how to create our own object types. In programming, an object is where we capture data and its behavior together in a single entity. Since the behavior code is provided for us by the creators of the class, this makes our job easier since we do not have to write that code, and in fact it enables us to use the objects without knowing all the details about how they work. Writing programs that use these objects is called object-oriented programming, and it can greatly reduce the amount of code and the complexity of that code when you create a program. As an example, we are going to explore the string class. Every object of the string class has a sequence of characters in it, plus a collection of methods that can operate on that string data, and it is all wrapped together in a nice little package. Objects are described by a class. The string class is a specification for the data that is held in every string object, in particular that a string object holds a sequence of characters and also the specification of the methods that can operate on that data. We already saw some string objects in earlier lectures in the form of string literals. The purpose of the methods, again, is to process or manipulate the data within an object in some useful way. For this to work, a method must know which object you want to process. To do this, we will use the same dot notation that we saw with the math class, but instead of using the class name before the dot, we will use the name of the object we want to process. When you do this, the method will be executed and it will process the data in the particular object on which it was called. Here are a couple of examples. In the first, we assign the string literal CDE to the string variable str1. In the second example, we are printing out the result of calling the concatenate method on the str1 object and providing the string xyz as a parameter. This gets the value of str1 and concatenates xyz onto the end, and the result is printed. Next, we have a string literal object, ABC, on which we are calling the substring method that will return the first two characters of the string. This new string is then assigned to the string variable str2. And finally, we print out the value of the string object str2, which prints the characters AB. So to review, to call a method of the string class, you must specify the string object on which you want to call a method, followed by a dot, followed by the name of the method, which is followed by any parameters inside parentheses. Now, when we call the concatenate method on the string object str1, it does not change str1. Rather, this method call returns a new value that is the result of concatenating str1 and the parameter string xyz. Since the method is returning a new value back to us, it is up to us to do something useful with that value, such as assigning it to a string variable, or maybe even printing it out. Here are a few other examples of string methods. The substring method will return the substring that goes from index x up to but not including index y. The starts with method takes a string as a parameter and will turn true or false, depending upon whether the string object starts that with that parameter or not. And the length method, which we use quite often, will tell us how many characters are in the string. Before moving on, it is important to note that several methods depend upon an index which specifies a position in the string, and that this indexing starts at 0 rather than 1, i.e. the first character of every string is at index 0, and the last will be at the index that is one less than the length of the string. Here are a few more string methods. The index of method will search for a substring and return its index if it is found, or the value minus 1 if not found. We already saw the length and substring methods, but we will note that there is an alternate version of the substring method that takes only a single parameter of the starting index, and will go from that point to the end of the string. The two lowercase and two uppercase methods convert all the letter characters to lower our uppercase respectively, and finally, the char at method will return the character at a specified index. There are many more methods in the string class, and the web has various reference guides and tutorials. To reiterate an important point that was made earlier, many of the string methods that appear to modify the objects on which they are called actually do not modify the objects, but rather they create new string objects and return them. For example, calling the two uppercase method on a string object S does not change the object S. If you want to change the object S, you must use assignment to assign the value that is returned by the method column. Finally, if you want to compare two string objects, you do not use the quality operator equal equal as you would with primitive data types. This will not give you the results that you expect. So if you want to compare two string objects, you should use the equals method from the string class. Since we are talking about strings, it is a good time to take a closer look at the primitive type char and the character class that has a collection of useful methods. The char data type, and again some people might pronounce it care, is a primitive type that allows us to store a single character. Character literals use a single quote mark in comparison with the double quote marks used for strings. And you can use the escape sequence to represent special characters. The string class has the char at method that will allow us to access the individual characters in a string object. In this example, we use the char at method to get the first letter at index zero from a string and then use that information to pronounce cookie monster song. Recall that internally to a computer, all data is represented as zeros and ones. As such, we need to specify what pattern of zeros and ones will be assigned to each character of type char. This is done by giving each character its own value called its ASCII value. This is simply an agreement or standard that says that the bit pattern whose value is 65 will represent an uppercase a, while the value 97 will represent a lowercase a. By the way, the standard also ensures that our alphabet is correctly ordered, which allows us to sort characters and strings more easily. There are times when we may want to convert a character to its ASCII value and back. If you add a character and an integer, the result will be an integer. If you want to convert that integer back into a character, it would require a type cast, as Java will not perform that conversion for you automatically. And just because every character has an ASCII value does not mean that you should use that value in programming. It is considered poor style to use hard coded ASCII values when you can use character literals instead. As we wrap up discussing the char type, let's make sure everyone understands the difference between char and string. We use double quotes to create string literals and we use single quotes to create character literals. They are two very different entities that behave differently. A string is an object and you can call methods on it. You can create new strings from it and you can find out its length, et cetera. While a char is a primitive type and as such it does not have methods. It only has the ability to store a single character. But just because char is a primitive type and does not have methods does not mean that Java leaves us high and dry. Java does provide a character class that provides a collection of character processing methods similar to how the math class provided a collection of number processing methods. The methods of the character class are all static methods and thus they are not called on an object. Rather you call them on the class name character similar to how we call the methods of the math class on the class name math. And whereas the methods of the math class took numbers as parameters the methods of the character class take characters as parameters. For example, if we had a character variable ch and we want to know if it contained an alphabetic character we could call that is letter method from the character class and pass the character variable ch as a parameter. Here's a partial list of the methods from the character class listing the method names, what parameters they take and what values they return. This lesson gave you an overview of Java string class. Now that you have completed this lesson you should understand the role of the string class in defining string objects and calling methods on those objects. You also now recognize some of the common string methods. In addition, you should be able to identify the difference between a string object and a character value. Finally, you should know the purpose of the character class and some of the methods it offers to clients. Welcome to our next lesson that explores basic Java features for developing Android apps which focuses on writing and calling your own methods. After completing this lesson you will understand why methods are such an important concept in Java programming. You will also know how to define a method and how to call it as well as understand what actually happens when a method is called. Moreover, you will recognize how to declare parameters for a method and how parameters are passed to that method. In addition, you'll be able to overload methods. Finally, you will learn how to return a value from a method and how to specify the value that will be returned. In this lesson, we are going to learn about writing our own methods. Before doing so, let's answer the question of why we need methods. Remember from an earlier lecture that an algorithm is a precise, unambiguous, step-by-step process for accomplishing a task. Here's a simplified example algorithm for building a Lego house. And here we see our algorithm converted into Java code. So far so good, right? Well, there is one problem in that our algorithm does not have any reusable parts. For instance, consider the task of building a two-story Lego house. If we look at our Java version we see that we have several identical lines of code that are repeated. This redundant code is very poor programming style. Since if we ever wanted to make a change to the building of the walls or windows, we would have to make those changes in two separate yet identical places. This leads to errors since it is common for someone to make a change in one spot but forget to make the change in the other spot. To solve this, Java allows us to define methods. A method is simply a group of statements to which we give a name. We can then use the name to execute the statements within the method. When we define methods, it is like adding new commands to the Java language that we can use. There are two types of methods in the Java language, static methods and member methods. Static methods are not associated with objects but rather independent helper functions. We have seen many examples of static methods in the math class and the character class. In contrast, member methods are associated with some object type and must be invoked on an object using dot notation. The methods of the string class which operate on string objects are all member methods. In this lesson, we will focus on static methods whereas member methods will be addressed in more detail in a later module in this MOOC. Here is the syntax that you use when you declare a static method. It has several parts that we'll go over one at a time. The keyword public specifies that everyone can call this method. All the methods that we create in this lesson will be public. In a future lesson, you will learn about private methods. The static keyword declares this method as a static method rather than a member method. If you were creating a member method, you would simply remove the word static. Next, you specify the type of the value that the method will be returning to the caller. This can be any known data type. If the method does not return a value, you specify void as the return type. Next, you specify the name that you want to call the method. Like other names in Java, it must follow the rules for an identifier. As always, the name should be descriptive of what the method will do for the user. Next is the parameter list that specifies the values that will be received when the method is called. We will address the details of the parameter list a bit later. If the method does not have any parameters, then the parameter list will be empty. Next, come all the statements that you want to have executed enclosed in the set of curly braces. When the method is called, these are the statements that will be executed one after another. So every method is made up of a header and a body. The method header is everything that is needed to be known to call the method. The method body is the code that will be executed when the method is called. Here's an example of a very simple method. This method does not return a value and does not receive any parameters and it simply prints some text to the display. To call a static method, you simply reference the method name and place the parameters inside the parentheses. If the method does not take any parameters, the parentheses are empty. For example, we can call the welcome message method that we defined on the previous slide and each time we do so, the same message will be printed on the display. When you call a method, your program will temporarily pause executing the calling method and branch to the called method and begin executing it. When the called method is done executing, the program will return to the point of the call and continue execution where it left off. This allows one method to call another method which calls another method which calls another method, et cetera, without us getting confused because every called method returns the point from where it was called. For example, consider the snippet of code that prints the first two days from the song The 12 Days of Christmas. The method 12 days calls the method day one and then the method day two. The method day one simply prints a line of text. The method day two prints a line of text and then calls the method day one and the output is shown below. Here's a graphical representation of what is happening. When the method 12 days calls day one, we start executing that method and when it is done, we return to the point of the call. At which point we call day two and start executing that method which in turn makes its own call to day one and we start executing day one method again. But this time when the day one method is done, we return to the point of its call which is in the day two method which then ends its execution and we return to the 12 days method. So it is good to define static methods whenever we have a group of statements that are related structurally such as building a wall in our Lego house or to eliminate redundancy if we have statements that are repeated in several places in our code. Next, we will discuss method parameters. A parameter is simply a value that a caller wants to pass into a method that is being called. We've already seen how this works when we discuss the math class and all its static methods. A parameter is a special type of variable that is declared in the method header and will be given a value each time the method is called. When you declare that a method accepts a parameter then calling that method requires that you provide a value for that parameter. When declaring parameters in a parameter list you must provide both a type and a name similar to declaring variables. Here's a simple example of a method which has a parameter called name which is of type string. Whenever someone wants to call this method they must provide a string value. When calling a method that expects a parameter you must supply a value and this value will be used to initialize the parameter before the method begins execution. Here we see a simple call to the say hello method where we pass the string dug. You can specify methods that receive multiple parameters by separating the parameters with commas. You must specify the type and name of each parameter and when you call such a method you must supply a value for each parameter. The values at the call are matched to the parameters of the method by position, the first value to the first parameter, the second value to the second parameter, et cetera. Java allows you to find methods that have the same name as long as the parameters of the two methods are different and can distinguish the two methods. We call this overloading. When methods are overloaded the compiler will look at the number and types of the parameters to determine which method gets called. We have actually seen an example of overloading earlier with the string class that has two different substring methods. One that has both a starting position and an ending position and the other that only has a starting position. Here's a useful example of overloading where we want to print the average of some values. One method will print the average of two integers while the next one prints the average of three integers and the last one handles two doubles. All three methods do the same type of thing so it's convenient that they share the same name. At this point it is appropriate to introduce the concept of scope. The scope of a variable is the portion of the code in which the variable exists and can be referenced. In Java the scope of a variable is from the point of its declaration to the end of the enclosing curly braces. In the sample code shown the scope of the variable X is from its declaration to the end of the method named example. While the scope of the variable I is only the two lines of code in the inner curly braces. The scope of a method parameter is the entire method in which it is declared. Now variables that do not have overlapping scopes can use the same name. This allows all our overloaded print average methods to also have parameters that reuse the same name. But Java does not allow variables with overlapping scopes to have the same name. When a Java method is called its parameters receive copies of the values passed in. This is known as call by value. In this example we have a method named double that receives an integer parameter. When we call it with three the method receives a copy of the three and prints the value six. When we call it with X the value of X is copied and the method prints the value 10. Note that variable X was not sent to the method but rather a copy of its value. Thus if the called method changes the parameter that change will not affect the caller since the method only receives a copy. In the example shown the method funny doubles the value of its parameter before printing it. But doing so does not affect the caller's variable X since only a copy of X's value was sent to the method. Note that due to scoping rules the variable X in the method process is a different entity than the parameter X in the method funny. Next we will discuss methods that return values. We have already seen methods that return values when we discuss the math class. All the methods in the math class return values to us when we call them. Now we're going to see how to create our own methods that return values. If a method is going to return a value to the caller you need to specify that in the method header. This is done by simply replacing the keyword void with a data type of the value being returned. Here's an example of a method that returns the value that is three times the parameter it receives. Note that the method header specifies that a double value is being returned to the caller. Now somewhere in the method body we must specify the value which we want to have returned to the caller. We use the return statement to accomplish that. Once we learn about control flow statements in the next module of this MOOC you'll be possible to have multiple return statements in the body of a method. Though it is often preferred to have only a single return statement at the bottom of the method. But it is important to understand that when a return statement is executed control returns to the caller immediately. A return statement always ends the execution of a method. Here are two examples of methods that return values. The first computes the volume of a sphere given its radius. And the second rounds a floating point value to two decimal places. And here we see the same methods that have been tidied up a bit by eliminating the local variables and simply having the return statement compute the value that is to be returned. On a closing note this lesson has focused on static methods that are usually helper methods that are not part of an object class. Again, object class will be seen in a later session. And all the methods would work if the out object we are using for printing were globally defined like the system.out object used in desktop computing. Unfortunately, in the Android world in which we are operating in this introductory class on Java the out object is not global but is rather a data member of the logic class in which we are currently doing all of our work. Thus, if you have a method that needs to access the out object for printing to the screen you will need to remove the static keyword from a method header for the method to work correctly. If you're helper methods simply take in parameters and return values and do not print anything to the out object then they can remain as static methods. This lesson introduced you to writing Java methods. Now that you have completed this lesson you should understand the concept of a method and why methods are so important in Java programming. You should also know how to define a method and how it is called as well as understand what actually happens when a method is called. Moreover, you should recognize how to declare parameters for a method and how parameters are passed to that method. In addition you should be able to overload methods. Finally, you should know how to return a value for a method and how to specify the value that will be returned. We have now arrived at the end of this module which lays the foundation of Java basics for programming apps on the Android platform. Now that you have completed the lessons in this module you should recognize fundamental concepts of writing an app in Java. You should also be familiar with the concepts of data types, variables, assignment and expressions. Moreover, you should understand how to print data, call mathematical functions and perform string processing. Finally, you should know how to define your own methods and understand why that capability is so important in computer programming. Now that you have completed this module you are ready to move on to the next module which discusses the various control flow constructs available in Java for Android. Now that you've gotten a better understanding of the Java language it's time to start thinking about control flow. Moving through a program line by line in sequential order is not the only way to execute code. Perhaps you would like certain lines of your code to repeat several times. Maybe you would like some parts of your code to execute only when certain conditions are met. Java has many constructs that can be used in these situations. Some examples include the if statement, for loop, while loop and do while loop. These control flow structures help you model more complex solutions to the problems that you may face when designing apps. By the time you finish these lessons you'll have increased your knowledge of Java by adding the constructs I've just listed. You'll also gain a deeper understanding of when to use these constructs to make code more readable, more efficient and easier to reuse in future projects. So let's get started. Welcome to the first lesson on the Java if statement that gives you an overview of conditional statements and relational operators which allow your programs to execute certain blocks of code and bypass others. After completing this lesson you'll understand why these concepts are essential to writing efficient Android apps. You'll also know how to program these concepts using the correct Java syntax. To motivate the Java if statement we'll use a simple game feature that conditionally changes the color of a player's avatar based on their location. This game reappears throughout this module to showcase how and when to use Java if statements. By now you've probably thought about things like what if I want to set max to 10 sometimes and sometimes I don't? Or what if I want to print out only the names of players with scores above 90? What you are searching for are conditional statements that determine if some action will be performed or bypassed and Java has a construct designed just for that. Let's start with a motivating problem. Suppose you are designing a game and you are coding a portion that sets the player's color. If a player moves into the northeast or southwest quadrants we want to turn the player green to symbolize that they're safe. If they move into the northwest quadrant the player would turn purple and if they move to the southeast red. In each case they are getting close to one of these monsters. Think about this problem for a minute. Pause the course and try to design a diagram when the location of a player is retrieved. If you'd like use the symbols like the ones shown on the screen. How did you do? Did you see the problem this way? We see first if the player is in the northeast quadrant. If not check the southwest. Either of these locations yields a green outcome. Otherwise continue by checking for the southeast quadrant and finally if needed check for the northwest. But there are some problems with this approach. For example, notice that the setting of green appears twice in our diagram. Also there's this awkward outcome where we don't quite know what to do. Let's look at another attempt at this problem. Now this diagram seems to have resolved one of our issues. With a more complex test in the first decision we can decide on the green coloring right away. But the idea of what to do at the last choice still leaves us with a problem. Let's get into the material and see what the Java language has to offer. To handle the types of choices we've just talked about Java uses the if statement. The simplest form is shown here. The diagram on the right illustrates the idea. If some test is true, the controlled statements the ones in blue boxes are executed. Otherwise they are bypassed. In either case the statements not controlled by the test are executed. Notice the syntax and sample. If the total is greater than or equal to 10 we would execute the print statement. And the reassignment of the variable total. Otherwise these statements in blue are bypassed. How do we create these tests? We're going to need to learn to write relational expressions. Each relational expression results in a Boolean value of true or false. We often call these Boolean expressions. Here's a table of relational operators that we use in Java which shows syntax for equals, not equal, less than or greater than and less than or equal to, greater than or equal to. Here are a few simple examples. Each Boolean expression results in true or false causing the controlled statements to be executed or bypassed. Let's consider a situation that could lead to a more complex Boolean expression. Suppose we want to test some variable X to see if it is between negative 10 and 10. This can be thought of as two tests like you see here. But we can do better. Consider these diagrams. On the left, we test for a number greater than negative 10 which can be many numbers such as negative seven or five or 17. Then we test to be sure those numbers are also less than 10. But these relational expressions can be combined with an AND operator shown here in Java as two ampersands. The single AND statement makes the code easier to read and shorter. Completing the diagram helps us to see the results of both outcomes of the relational expression. Here's the code of a compound Boolean expression. Using the AND or double ampersand makes this code shorter and still very readable. It better reflects what we are trying to model. There are several logical operators we use in Java. They are the and or and not operators. The truth table below, a common tool used in logic classes shows the outcome for each of the two binary operators and an or. Notice if two expressions P and Q are both true, then we evaluate P and Q, the result is also true. P or Q results in true as well. However, when either P or Q is false, the AND statement is no longer true, but the OR statement is. Finally, when both statements are false, both operators will yield a false Boolean value. The NOT operator changes the value from true to false or false to true. Armed with these concepts, let's return to our game. Now we know how to form the Boolean expression to evaluate if the position is in the northeast or southwest quadrant. If our location matches either of these quadrants, the expression would be true and we would color our player green or safe. Players who fail the test would be considered unsafe as they are dangerously close to one of two monsters. All that's left is to color the player red or purple. We currently have a test for southeast and one for northwest, but let's take a closer look at the outcomes. A player must always be in one of the four quadrants and let's just assume location 00 would be considered northeast. When we discover the player is not northeast or southwest and we then test for southeast, what are the possible outcomes? Either our player is in the southeast quadrant or they must be in the northwest quadrant. There's no need to test for northwest. Instead, we can simply assume that if they aren't in the southeast quadrant, they should be colored purple. In our next lesson, we will examine a few other common forms and uses of the if statement. We will also return to our game and begin to put together the code. Now that you've completed this lesson, you should understand why conditional statements and relational operators are essential to writing efficient Android apps. You should also know how to program these concepts using the correct Java syntax. By understanding conditionals, you have added more capability to your expanding knowledge of Java and Android programming. Welcome to part two of our lesson on if statements in Java. In this section, we explore another type of if construct that can lead to better Java programs when there are multiple branches to consider in conditional statements. After completing this part of the lesson, you'll recognize when to use multi-branch if else statements and begin to understand how to analyze problems and apply the appropriate type of if statement. Recalling our previous lesson, we looked at a very simple if statement. It allowed us to test some condition. If that condition was true, a set of statements was executed. Otherwise, they were bypassed. Let's now consider other scenarios that would require several different paths through several different sets of statements. Here we have stacked several if statements on top of each other in an attempt to offer different prizes to students depending on how many magazines they sold at the school fundraiser. If total sales top 50, the student will win an iPad. If they only sell 35 or more, they still get an iPod. Moving down the price scale, if they sell 25 or more, they will win a nice stylus. Prizes continue for the group selling 15 or more until finally there is an option of just getting an encouraging message. Do you see the problem with this code, however? Suppose we sold 72 magazines. Passing the first test, we would get an iPad. Moving down the code, we would also pass this test because 72 is greater than 35. We'd take home an iPod as well. This bonanza of prizes would continue until we cleaned out the place. That was not the original intent of the program. We could change the conditions or tests to make them more explicit. For example, our second condition should be sold is less than 50 or greater than or equal to 35. But then a student who sold 72 magazines would still have to run through every condition, even though we knew after the first test that he or she would not pass any of the others. This type of coding would lead to an inefficient program, one that runs much slower doing much more work than it needs to. What we really need is something more like this. If the number of magazines sold was greater than or equal to 50, then the reward is an iPad. Otherwise, if the number sold is greater than or equal to 35, the reward will be an iPod. Otherwise, the number sold is greater than or equal to 25, the reward is a stylus, and so on. This diagram won't allow for this type of construct. We need to be sure that once a test has been passed and some set of controlled statements, like winning a prize or executed, the rest of that code is bypassed. This code will do it. Notice that if the number of magazines sold is 31, the blue line of code is executed, and then the rest is bypassed. But this is considered poor style because of the deep nesting. Imagine if you have 17 different category surprises. This code would run quite wide with all that indentation. Let's look at an alternative structure that might do the trick. The multi-branch, if-else, is ideal when we have many conditions to test for, and each pass through the code would result in only one of those controlled statements being executed. In this example, we have three groups of conditions. The red, blue, or green. These three statements can be controlled with only two tests. The final condition, here shown in green, is sort of a catch-all for input that didn't pass any of the other conditions. Here we test to see if input X is positive, negative, or zero. All numbers in this program will fall into one of the three categories. But we haven't seen it all yet. Suppose there is a case where we would want to bypass all of the possible statements. That is impossible here. We need an if-else, if, that allows for that bypass. Here, every statement is controlled, and to execute any of them, a test must be true for the input. This works well for our example where we have a message for students earning a grade of A, B, or C, but no executable statement otherwise. Take a moment now to review all of the different ways we can use if statements to control what code does and does not get executed. Create a few scenarios that might require the different constructs we've seen today. In each case, look at how many different outcomes are possible, like in the magazine sales, where we had four different GIF levels. Does your code need the option of bypassing all the conditions? This was not true when we were displaying whether a number was positive, negative, or zero. It was true in the case of students earning an A, B, or C. In all cases, be on the lookout for redundancy. Are you testing for some condition more than once? Perhaps you can combine tests or reorder them so that that does not occur. Now that you have seen a wide variety of if statements, let's return once again to our game and the problem of coloring our avatar based on the current position. We have three conditions, purple, red, or green, and every player will fall into one of these conditions. The code should not allow for a bypass here. Think you're ready to tackle this one? Let's assume the player's position is given as x, y coordinates, p1.x and p1.y. Note that positive x times positive y equals positive result, northeast quadrant, and green. Likewise, a negative x times a negative y also will give you a positive result, indicating the southwest quadrant, also green. Positive x and negative y multiplied together will result in a negative number. This means you're in the southeast or red quadrant. Negative x times positive y, also giving a negative result, shows you are in the northwest or purple quadrant. Try writing the code, keeping all that you've learned today in mind. Did you come up with something like this? The two positions that color the avatar green can be grouped together by testing to see if the result of the multiplication of p1.x and p1.y is positive. If it is, the color of the avatar is changed to green and that position will not be tested any further. Otherwise, or else, we can check to see if x and y are not the same sign by testing p1.x. Notice that although p1.x will be positive for an avatar in the northeast quadrant, that has already been colored green and won't be tested again. Finally, there's no need to test for this last case. If an avatar isn't going to be green or red, it must be purple. These tests could be rearranged in a number of ways. For example, testing p1.y to see if it was negative in that second condition. But the best structured code would only need two tests or conditions to discern between these three groups or locations, the green, red, and purple. Consider trying some of the code walkthroughs for further practice. This concludes our lesson on if statements in Java. Now that you've completed this part of the lesson, you should recognize when to use multi-branch if-else statements as well as better understand how to analyze problems and apply the appropriate type of if statement. With your increased knowledge of conditionals, you've added to your growing ability to write Java programs in Android. Consider trying some of the code walkthroughs for further practice. This short video will walk you through a simple Java program that uses several if statements to solve a problem. The code was written in Android Studio. A user indicates the current weekly mileage they are running, the distance of an upcoming race they hope to compete in, and the number of weeks until the race is held. Let's take a closer look at the code. We can see these first three lines gather the necessary information from the user. We use the race distance indicated by the user to determine the number of miles a runner should be logging before the race date. We use the race distance indicated by the user to determine the number of miles a runner should be logging per week by the race date. There are three race distances and every selection will fall into one of these three choices, the half marathon, the 10K, or the 5K race. For simplicity, we have used characters to signify the user's choice. Let's assume the user has entered their choice from a menu, A for half marathon, B for 10K, and C for 5K. Let's also assume that the user input only A, B, or C, and no other character. Keep that idea in mind. The knowledge you will gain when you have completed this entire module will help you to build the code needed to write these sorts of checks and ensure the validity of user input. Assuming the user has a choice from only the three menu items, we would need three paths through the if block that would call for two tests. Here an if else if will work well. If the user chose the half marathon or A, their goal weekly mileage will be set at 30. If they chose the 10K or B, their goal weekly mileage will be set at 20. Otherwise they must have chosen C, the 5K, and we set the mileage at 15 miles. To determine if the runner can achieve that goal mileage in the number of weeks they have left to train, we need to do a bit of math. If you're not interested in deconstructing this calculation right now, just skip through the next two slides. A good rule of thumb for runners is to increase their mileage by no more than 10% per week. In week one, a runner can therefore log 10% more miles than they ran before they began using this app. That's the current mileage times 1.1. In week two, the runner can add an additional 10% of mileage. Notice that is 10% more than what they ran last week. So we multiply week one's mileage by 10% or 1.1. We can simplify that calculation to current mileage times 1.1 squared. Noting a pattern here, we can see that in week K, the runner will be finishing current mileage times 1.1 to the K power. We know the goal mileage already. What we don't know is how many weeks it will take to reach that goal mileage. Therefore, we must solve for K in this equation. Using some pretty straightforward math, we see that our final equation is not a pretty one, but it does give us our answer. We will need to round up or take the ceiling of our final calculation to arrive at a whole number or integer answer. Returning to our code, you can see the two lines of calculation we used to solve for the number of needed weeks. With that number, we need to say if the runner has enough time to reach that goal. We must compare the needed weeks to the number of weeks the user has input. We first check to see if the user can meet the goal. Are the needed weeks less than or equal to the weeks available that the runner has input into the app? If there is enough time, we'll print out some instructions on training. If there is not enough time, we need to print a message letting the user know that the choices they have indicated won't work, but they may be able to select a shorter race and try the calculations again. So now we need to see if they've chosen the 5K race or C. If they have, then there's nothing left to suggest. But if they've chosen the 10K or half marathon race, then we can suggest they look at running a shorter race and thus decrease their goal mileage. Here is the code for the second if block. First, we check to see if they can accomplish the goal in the allotted number of weeks. If they could not, we begin to print out the appropriate message. Here, we used an embedded else statement as opposed to the if else if we used in the first code block. This allows us to execute these output statements. Then, continue with a second conditional. If the user has chosen that shortest race, then we simply end the message here. Else, we continue the output by suggesting a shorter race. In all cases, a good luck message is printed at the end. Here is a look at the entire code with some helpful diagrams of the if blocks. The if else if blocks allows us to determine which of the three races a user has chosen and assign goal mileage based on that choice. The nested if statements make it possible to execute lines of code in steps, depending on the result of several conditionals. All together, we have an easily readable process that produces the correct output every time. Welcome to the first lesson on the Java for loop statement. This lesson will give you an overview of iteration, which allows your program to repeatedly execute certain blocks of code until some condition is satisfied. After completing this lesson, you'll understand why iteration is important to writing Android applications. You'll also know how to program these concepts using the correct Java syntax. To motivate the Java for loop, we'll use an example that repeatedly prints strings to your display. This example reappears throughout this lesson to showcase how and when to use the Java for loop. Before we consider Java's for loop, let us answer the question of why we need some type of looping construct after all. What does a loop buy us anyway? Let's consider the simple example of a timer counting down from 10 all the way to one. Notice that the only thing that is being done is the displaying of an integer value. So the work that is being done, displaying an integer, is the same. It is only the integer value that is changing. With what we have learned to this point, you can accomplish this task with a simple set of print statements as is shown in this slide. This works, but is rather tedious and repetitive for us the programmer. And this is a terrible waste of our time. It takes a programmer about two seconds to type out a line of code, but it only takes a computer fractions of a second to execute each line. And weren't computers invented to free us from tedious and repetitive tasks? Even worse is if we want to change the starting point of the timer. To do that with our current code would require us to edit the source code of our program and delete or add more lines of code so that we could start at five or at 15 or yikes. We won't even consider starting at 500 using this strategy. So this is a key point about the importance of loops. Loops allow the program to specify a set of instructions to be executed and then tell the computer to execute them again and again. Java has several loop constructs. We will start by considering the for loop in this lesson. Let's consider the simple segment of code. We have five print statements that print values that have been doubled. These statements when executed will print five lines of output on the screen. Logically, the code is doing the same thing for each number from one to five and we would like to capture that fact without so much redundancy in the code that we have to write. In fact, wouldn't it be nice if we could write only a single print line statement? Well, Java's for loop does just that. Rather than writing five print line statements, we will write a single print line statement and add code to specify that we want that print line statement executed five times. And the for loop doesn't care how many times it has to do the work. We could easily make the loop execute print line statement five thousand times. This simple for loop, as it is written, basically says, for each integer i from one to five do the following. To learn about for loops, let's take a closer look at this code that prints out the five doubled integers. It consists of the code inside the curly braces. This is the code that we want to have executed repeatedly. This is known as the body of the loop. And then there is the code before the open curly brace that starts with the keyword for. This is known as the loop header and it controls how many times the body of the loop will be executed. The loop header starts with the word for and is immediately followed by three expressions inside parentheses. The three expressions are separated by semicons. Note there is no semicolon after the third expression. The first expression isn't the initialization part. It is only executed once when the for loop begins its execution. This expression declares what variable the loop will use to control its execution and gives that variable an initial value. In this case, we are declaring that the loop will use the integer variable i and it starts out with a value one. The second expression is the loop test. This test must evaluate to a true false value. And as long as that value is true, the body of the loop will be executed again and again. This test expression is reevaluated before each execution of the body and the body is only executed if the test continues to be true. For now, the test that we write will use simple relational operators that allow us to compare two numbers. In this example, we want to know if the variable i is less than or equal to five. If i has the value one, that expression is true. If i has value six, that expression is false. And finally, the third expression of the for loop header is the update expression. This is an expression that is intended to change the loop variable in some manner so that we get closer to causing the test expression to evaluate to false. It is important to note that the update expression gets evaluated only after the loop body is executed. So during the execution of the loop body, the loop variable still has the value that caused the test expression to be true. So if the test expression is true, the loop body is executed. When we hit the closing curly race of the loop body, then the update expression is evaluated. And we continue with evaluating the test expression again. Note that the update expression can be any expression that updates the loop variable. It might be adding one to the loop variable or subtracting one or multiplying it by five or whatever is needed. Most often we simply want to add one to the loop variable and so we can use the increment operator plus plus. Finally, when the test expression evaluates to false, execution of the program continues with whatever follows the for loop. Here's a nice visual showing how a for loop behaves. We start by evaluating the initialization expression. This occurs only once. We immediately evaluate the test expression and if it is true, we will execute the body of the loop and immediately evaluate the update expression. And that brings us back to the test expression. If it again evaluates to true, we will execute the body again and the update expression again. And again, we come back to the test expression. And as long as they evaluate to true, we continue executing the body and performing the update. Now, if we have written our code correctly, eventually the update expression will cause the test expression to evaluate to false. At that point, the loop exits and we continue executing the code after the loop. Now that you've completed this lesson, you should understand why iteration is important to writing Android apps. You should also know how to program these concepts using the correct Java syntax. The remaining lessons on for loops will explore other ways of iterating through a range or sequence of data in Java programs. Welcome back to our discussion on for loops in Java. In this lesson, we'll explore additional ways to use this looping construct to write better Java programs. After completing this lesson, you'll understand how to use for loops in various situations effectively. You'll also know how to use for loops to some terms in a series. Moreover, you'll recognize how to make for loops count down rather than count up. Finally, you'll be able to identify some common problems that can occur with for loops in Java. In the previous lesson, we examined the for loop statement that allowed us to repeatedly execute some code a set number of times. After performing the initialization, the loop condition was evaluated. If the condition was true, a set of statements was executed followed by the loop update expression. As long as the loop condition was true, the body and update expression were executed. Once the loop condition was false, the loop was exited. In that lesson, the for loops that you saw all use the loop counter variable in the body of the loop in some manner. But that is not a requirement. We might just want a for loop that repeatedly executes some code, but that code does not care about the value of the loop counter variable or which iteration of the loop is executing. In this simple example, we use a for loop to print the word love a specific number of times. Another use of for loops is in computing a series. In mathematics, a series is the sum of a sequence of terms. They are used to compute various special mathematical functions and constants. We use similar loops for computing all sorts of results. They are so common we give them a special name, cumulative sum loops. Such loops start by initializing a variable that will act as our accumulator, depending upon what we are summing, the variable could be of type int, double, or even string. The for loop is then written to iterate over the desired range of values. And the body of loop adds the next term of the series into the accumulator. When the loop exits, the accumulator variable will contain the desired result. Here, in this example, we have a cumulative sum loop that is computing our harmonic series, which is the sum of one plus one half, plus one third, plus one fourth, et cetera. And the for loops are not restricted to starting at one and counting up by one each time. Here you see a loop that starts at two and doubles its value on each iteration, stopping when the value passes 2,500. This loop adds those values into an accumulator named sum, thus resulting in the summation of all the powers of two between two and 2,500. You can also have loops that count down rather than count up. Here is an example of a for loop whose loop counter variable starts at five and which is decremented by one on each iteration. This loop continues executing as long as the loop variable is greater than or equal to one. You need to be careful to modify your loop test correctly so that the loop continues as long as the loop counter variable is larger than some target value. As can be seen, this loop will count down from five to four to three to two to one before finally exiting the loop. Finally, as you write your for loops, you should be aware of some common problems. One such problem is writing a loop that executes zero times. Here's such an example. You see a for loop whose loop counter variable i starts at 10 but the loop test says while i is less than five. But since i starts at 10, the loop test is false before the loop even begins to execute. Now as a result, the body of this loop is never executed. And worse than a loop that never executes is a loop that never quits. Here's a for loop whose loop counter variable starts at one and the loop test is while i is less than or equal to 10 which is true and thus the body of the loop is executed. But when you come to execute the update expression, here is a common mistake. You see, we have a post increment expression combined with an assignment operator. When this executes the expression on the right hand side of the assignment operator is evaluated. This is the post increment operator. Thus it increments the variable i changing it from one to two. But since it is a post increment operator it returns the original value of i as its result and that is the value one. This value is then assigned to i on the left hand side of the assignment operator changing i back to one. The end result is that i did not get changed. And as a result, i will always be less than 10 and the loop test will never fail and thus this loop will execute forever. We call this an infinite loop. Another common problem is typing a semicolon after the for loop header. This semicolon forms the body of the for loop resulting in an empty loop body. The code in the curly braces is not the loop body in this case and will only get executed after the for loop is done executing. In this example, the for loop will repeat 10 times but does nothing on each iteration. Only after the loop exits will the printlin statement in the curly braces be executed. This lesson explored various ways to use for loops to write better Java programs. Now that you've completed this lesson you should understand how to use for loops correctly in a wider variety of situations. You should also know how to use for loops to some terms in a series. Moreover, you should recognize how to make for loops count down rather than count up and be able to identify some common problems that can occur when you use for loops in Java. Welcome back to our discussion on for loops in Java. In the two previous lessons we examined the for loop and how to use it effectively. This lesson explores nesting for loops inside other for loops. After completing this lesson you'll understand how to write nested for loops and how they work. You will also understand how to use a common variant of nested loops called a triangular loop nest. You will then be able to apply these concepts to solve problems that require these principles. Finally, you'll be able to identify some common problems that can occur with nested for loops in Java. So let's get started. To motivate the topic of this lesson let's consider the task of printing a multiplication table of the integers one through 10. Such a table has the numbers one through 10 heading each row and the same numbers heading each column and their intersection in the table contains the product. Here's an example of the output we wish to produce. Notice that there are 10 rows of data and each row has 10 numbers that are printed. To get the columns to a lineup we will print a tab character after each number as we print the numbers across the row. Let's start by writing a for loop that executes 10 times. Here we have a loop that iterates i from one to 10. Now when we add code to the body of this loop we can add any kind of statement we wish. It could be conditional statements, method calls, or more interesting to us right now it could be another for loop. If we add a for loop inside another for loop we need to use a different variable for the loop counter. Otherwise the loops would interfere with one another. In this example we have added a for loop that uses a loop counter variable j. When discussing these loops we will distinguish them by their loop counter variable. For example we will name the outer loop the i loop and the inner loop the j loop. When loops are placed inside other loops in this manner we call them nested loops. In this case the j loop is nested inside the i loop. So what will actually happen when we could execute this code? It seems difficult at first to keep track of all that is going on. In this example the outer i loop will execute 10 times for i start at one while i is less than or equal to 10. On each of those 10 iterations of the outer i loop all the statements of its body are executed. That includes the inner j loop. That means the inner j loop starts all over again setting the loop counter variable j to one and repeating its body while j is less than or equal to 10. Thus the inner j loop executes 10 times for each of the 10 iterations of the outer i loop. As a result the print statement in the j loop is executed 100 times. Now let's consider this slight variation to our loop nest. In this code instead of the inner loop executing while j is less than or equal to 10 it is executing while j is less than or equal to the loop counter variable i. Since i has a different value on each iteration of the outer i loop the inner j loop iterates a different number of times. When i is one the j loop iterates only once. When i is two the j loop iterates twice. As a result the number of values printed on each line grows as the value of i grows. We see one multiple printed on the first line two multiples printed on the second line all the way down to 10 multiples printed on the 10th line. Due to this triangular pattern of the iteration space we call such nested loops triangular loops. Now what if we wanted a different triangular portion of our multiplication table? In this case we want to get the values above the diagonal with 10 multiples on the first line all the way down to only one multiple on the 10th line. It appears we simply need to make the inner j loop count down from 10 to i. This j loop will execute 10 times when i is one and it'll execute nine times when i is two down to only executing once when i is 10. Unfortunately this also changes the values of the multiples being printed. So we get the correct iteration space but not the correct values as can be seen in this slide. There are a couple of ways to fix this so that we keep the same iteration space but get the correct values of the multiplication table. One way to fix this is to change the j loop back into a loop that counts up from one. However we change the j loop limit such that it is smaller on each iteration of the i loop. We accomplish that by subtracting the value of i from a constant. This triangular loop test will result in the correct values being printed above the diagonal. Next we will consider drawing figures on the screen made up of only ASCII characters that appear on a keyboard. We call this ASCII art. This is a great way to exercise writing nested loops of different types. There is one guiding principle for creating such art. The outer loop controls the number of lines to be printed while the inner loops control the contents of each line. This is just what we saw with the example of printing different portions of the multiplication table. For our example let's consider the problem of drawing an equilateral triangle made up of stars. Here we see two examples. A size four triangle and a size six triangle. Notice how each side of the triangle is made up of the same number of stars and how the star at the top of the triangle is centered over the base of the triangle. To draw such a triangle given a specified size, we would need an outer loop to control how many lines get printed. We would want this loop to iterate for size times. Then the body of this loop will contain a nested loop to print the correct number of blanks or spaces so that each line is correctly indented. Since the amount of indentation changes on each line, this will need to be a triangular loop. We then need another loop to print the stars for that line. Since the number of stars increases with each line, this will also need to be a triangular loop. So we start by reading the specified size of our triangle. We then create the outer loop that will control the number of lines printed. Here the eye loop starts at one and continues until it exceeds the specified height. Next we create the inner triangular loop that controls the printing of the spaces that produces the desired indentation. Since the number of spaces decreases as we print more lines, we will use a loop that counts down. Conversely, we could have written a loop that counted up but iterated fewer times by subtracting the value of i from the value of height, similar to what we saw earlier in the triangular multiplication table. Next, we create a separate triangular loop that controls the printing of the stars with one star on the first line, two stars on the second line, et cetera. And after our row of stars are printed, we then print a new line character to end the current line. Finally, before closing, let's discuss two common errors that people make when they create nested loops. The first problem occurs when the test expression of the inner loop accidentally tests the outer loop counter variable rather than the inner loop counter variable. In this example, the inner loop is testing the variable i. And since i does not change in the inner loop, the test is i less than or equal to 10 will always be true. And we end up with an infinite loop. The second common error is updating the wrong loop counter in the inner loop. In this example, the inner loop is testing the inner loop counter variable j but is updating the outer loop counter variable i. Since inner loop counter variable j is not updated, this will also result in an infinite loop. This lesson explored nested for loops and showed examples of using them to write more complex Java programs. Now that you've completed this lesson, you should understand how to write nested for loops correctly and how they operate. You should also know how to write triangular loopness as well as be able to apply nested loops when required and identify some common problems that can occur when these types of loops are used in Java. With your increased knowledge of iteration using for loops, you've added to your growing ability to write Java programs in Android. Consider trying some of the code walkthroughs for further practice. This short video will walk you through a simple Java program that uses a for loop and if statements to solve a problem. The code was written in Android Studio. In this example, we are writing the code to compute the score for a simple word game being played on the Android device. Our program will receive a word from the user which is entered as string data. The score for the word is computed by awarding two points per letter. But the word is worth double those points if the word is four or more letters and the number of vowels in the word is greater than or equal to the number of consonants. To compute the score, we need to determine the number of letters and the number of vowels and then compare the number of vowels to the number of consonants. For this program, we will assume each word is only composed of alphabetic letters. First, let's compute the number of letters in the word. This is very easy as we only need to call the length method on the string object. We will store this count in the integer variable numChars. Next, to count the number of vowels, we need to look at each character in the word. To accomplish that, we will use a for loop to iterate over the characters of the word and access each character using the char at method of the string class. Recall that characters in a string are accessed using zero-based indexing. Thus, the first character is at index zero, the second character is index one, and the i-th character is at index i minus one. So we write a for loop whose loop counter variable starts at zero and is incremented by one each generation and which stops when it reaches the length of the string. We can then use the counter variable in the char at method to get the next character from the string. We store each character in a local variable named ch. Since we want to count the number of vowels, we will use a cumulative sum loop. Thus, we introduce an accumulator variable and initialize it to zero before the loop. And inside the loop, whenever we encounter a vowel, we will increment the accumulator. To determine if the character is a vowel, we will convert the character to lower case and then compare it against the lower case vowels. Here's the code we have to this point. After getting the word, we get its length. After that, we set up the cumulative sum loop and iterate over all the characters of the word. For each character of the word, we convert the character to lower case and then compare it to the five vowels. If it is a vowel, we increment the accumulator. Now we are ready to compute the score. Again, the user gets two points per letter and gets double that if certain conditions are satisfied. We start by initializing the score with the number of letters times two, thus awarding two points per letter. We then need to determine if the word is worth double points. That is true if the word is at least four letters and if the number of vowels is greater than or equal to the number of consonants. A simple if statement with a compound condition satisfies our needs here. Putting it all together, here is our final code. Welcome to the next lesson in control constructs, which focuses on two new forms of indefinite loops, the Java while loop and do while loop, which continue to iterate until some conditions are met. After completing these lessons, you will know the proper Java syntax for programming these loops, their capabilities and limitations and when it is best to use them in your code. Suppose I would like to reduce a number by three until it is less than or equal to 19. How many times should this loop be executed? Or what if I'm asking the user to guess a number and I wanna continue until they get it right? How can we make a loop that will continue to run under these conditions? What we are talking about here is a loop that can run indefinitely. As long as some condition is true, we will execute the protected code seen here in green. When the condition or test becomes false, we exit the loop and continue with the rest of our code. The while loop will do exactly that. It repeatedly executes the code written in the body until some logical test is no longer true. Here's the syntax for a while loop. Take a look at this example. While num is greater than 19, I continue to subtract three. We repeat until the number is no longer greater than 19 when we exit the loop and continue the rest of the program. A while loop is similar to a for loop and can actually be used in place of a for loop. We initialize I, test I, and increment I in much the same way. A for loop can take the place of a while loop, but this often results in poorly structured code that is difficult to read. To replicate the while loop on the right, we need to set up an infinite for loop by setting I to zero, test to see if I is greater than or equal to zero, and then continue to increment I. So do you see how this loop is going to be infinite? In the loop, we test to see if num has become less than 19. And if it has, we set I to some value that will stop this otherwise infinite loop. In this case, we had to set I to negative two so that when we increment I after the body is executed, we still have a value that's less than zero. There are other ways to write this for loop, but none of the solutions are going to be very readable. A good programmer will adopt the practice of using indefinite loops when the number of iterations is not known or easily calculated beforehand. The syntax of the while loop is almost identical to that of the if statement, but the results are quite different. In the if statement, the conditional total less than five is tested only once, and the total is increased once or not at all. In the while loop, the condition may be tested many times before we finally exit the loop. There are a lot of situations where a while loop is useful. For example, when interacting with a user. In this case, we can ask the user to enter a number with some constraints and then read it in. If the input does not meet the constraints, we enter the while loop and ask the user to try again. We read in the input and return to the top of the while loop to test the new data. This will continue until the user has input a valid number. You may have noticed in that last example that there was some redundant code. We had to write the next int code twice. In many cases this can be avoided by using another indefinite loop, the do while loop. The do while loop is also considered an indefinite loop and is best used when the number of iterations is unknown but we expect to run the protected code at least once. Notice how the diagram for this loop is slightly different. When we enter the loop, we immediately execute the body of the loop once. Then test the conditional to determine if we will execute the body again or exit the loop altogether. Here is the syntax for a do while loop. Notice the test or conditional is at the bottom of the body of the loop. Here, let's look at an example. Notice that this code is enclosed in an if statement. We only enter the body of the if statement if our number is greater than three to begin with. We print out a statement and then enter the loop. The loop is executed once, printing out the number three. I is then incremented and then we test num. If num is still greater than three times I, in this case six, we re-enter the loop. Execute the body, test the condition again. Now you have seen some examples of two indefinite loops, the while loop and the do while loop. We reviewed when is the best time to use these constructs and how they differ from the for loop and the if statement. Take full advantage of the code walkthroughs, quizzes and peer assessments to familiarize yourself with all of the basic control flow constructs you have seen thus far. We're now done with this module's final lesson on looping which introduced you to the Java while loop and do while loop. These indefinite loops continue to iterate until some conditions are met. Now that you've completed this lesson, you should know the proper Java syntax for programming these loops, their capabilities and limitations and when it's best to use them in your code. Welcome to our final lesson in this module on Java control flow constructs which does not introduce a new control flow construct but instead discusses a Java class that's most useful when we have the ability to use it inside a loop. That class is called random and instances of it can be used to generate a stream of random numbers. After completing this lesson, you will understand the concept of random numbers and appreciate their importance in the field of computing. You will also know how to declare an instance of the Java random class and be familiar with the methods that you can call on that object. Finally, you will recognize how random numbers can be used in simulations and in other common computational apps. In this lesson, we're gonna learn about Java's random class but before we do so, let's discuss why we need random numbers in the first place. Computers have changed many areas of society because they can process so much data very quickly but even more than that, they can also generate a lot of data very quickly. This data generation is usually required to be random since the process we are attempting to simulate is itself random. Now sometimes mathematicians and statisticians are able to come up with the answers we are looking for but often the problem is too complicated to be modeled by a single formula and thus a computer simulation is the next best thing. In fact, such simulations are so important that they have been given their own name, Monte Carlo methods. Such problem solving strategies rely upon the generation of random data to compute their results and are used to simulate all types of systems in business and science. We will not talk any more about Monte Carlo methods here but Wikipedia has a long list of applications for the interested student. To support the generation of random numbers, Java has the random class. This class will allow us to generate what is known as pseudo random numbers. That just means they are not truly random but they appear random enough for all practical purposes. The random class has many methods but the more common ones are listed here. They are next int which returns a random integer. Next int which takes an integer parameter which we call max and which returns a random integer from zero up to but not including max and following the method next double which returns a random floating point value from zero up to but not including one. The random class is a part of the Java util package and so if we want to use it we must have an import java.util.random statement at the top of our Java file. Then later in our code we can create a random object by saying new random and assign it to a variable type random and at that point we can then invoke class methods on the object. Here are some common applications of a random number generator. To generate a random integer in the range one to n you would use next int method and provide n as a parameter. This returns an integer in the range zero to n minus one and so you simply have to add one to that value to shift it up or to generate a random integer in any given range you can use the next method and use the size of the range as a parameter. That value then just needs to be shifted by the lower bound of the range. For example, to generate a value in the range 41 to 45 we use next int five and then add 41 to the result. You can also use random numbers in text processing. For example, we can generate a random lowercase letter or we can pick a random letter from a string such as picking a random DNA nucleobase from a string containing all possible bases. The next double method returns a floating point value in the range zero up to but not including one. You can create a random floating point value in any range of numbers by multiplying the result of next double by the size of the range and then shifting that result by the lower bound of the range and any random process which has a finite set of outcomes can be simulated by mapping the possible outcomes to the integers. For example, to flip a coin we can generate a random zero or one. To play rock, paper, scissors we can generate a random zero, one or two. Here's a simple example of using random numbers. Say we want to simulate the rolling of two dice until a double is rolled. We roll the two dice and report their values until they have the same value. In this example, we finally rolled a double three and then stopped. And here is the code to run the simulation. We first create a random object and we declare a cumulative sum variable to keep track of the number of rolls. Then in a do while loop we get a random number in the range one to six for each die and print out their values. We also increment our variable that is keeping track of our number of rolls and we keep doing this while the two die are different. When we finally roll a double and both die have the same value we exit the loop and print the final message. This lesson gave you an overview of Java's random class. Now that you've completed this lesson you should understand the importance of random numbers and know how to declare an instance of the random class. You should also be familiar with the methods of the random class and be able to identify what they do. Finally, you should recognize how random numbers are used in simulations and other common computational apps. Now that you've completed this module on control flow in Java you should have a good understanding of how to structure your Java programs so that you can achieve the desired result. If statements allow you to control when code is executed by setting up certain conditions that must be met before the body of an if statement will be run. A well-written for loop will run a predetermined number of times. The while loop and do while loop execute their statements until some condition is met. By adding control flow to your growing knowledge of Java you are now able to create programs that can model many different scenarios. Welcome to the next module in our MOOC on Java for Android programming which focuses on constructs for storing and processing collections of structured data within a single object. After completing the lessons in this module you will understand how Java arrays work and how to access and process arrays efficiently. You will also recognize the key classes and interfaces in the Java collections framework. Finally, we will explore several classes from this framework in detail including array lists and hash maps. So you will learn how they work what their pros and cons are and how to use them effectively to create Android apps. In this module we are going to explore Java's capabilities for storing structured data. To help motivate the need for the subject let's consider this sample problem. Say we want to compute the average test score for a classroom of students where the number of students may vary from class to class. Given this problem a little thought we determine that we can easily write a solution for this with the knowledge we have so far. We can simply read in the number of students and then create a cumulative sum loop that will iterate the specified number of times and read in each student's score and add it to the total. After reading all scores and exiting the loop we can divide the total by the number of students to compute and report the average. It is a simple straightforward solution. Now consider this slight twist to the problem. Besides computing the average we also want to report which scores were below the average so that we can give extra help to those students. To solve this new problem we need each test score twice. Once so that we can compute the average and then again to compare it against the average. We might be tempted to create a variable for each test score but since the number of students can vary we don't know how many variables to create and such code would become unruly if there were more than just a few students. So with our current knowledge of Java we cannot come up with a good solution to this problem. To solve this problem we need a way to store a whole bunch of data together and we need to be able to treat the collection as a single entity but still have access to any individual piece of data in the collection. We need to be able to process all the data elements in the collection in an easy manner and we need to access the elements as many times as needed and in whatever order needed. All of these are very important capabilities that we have carefully avoided up to this point. Java has several different solutions that we could apply to this problem and to similar problems. We will consider arrays first since they are the oldest and most standard structure found in programming languages. In addition to arrays, Java also has the collections framework which contains several structures that we can use. The collections framework contains many structures including lists, maps, sets, cues, et cetera. The structures have different properties so that a program can choose the most appropriate structure for any given problem. For this class we will only have time to look at array lists and hash maps. Welcome to the first part of a multi-part lesson in this module on structured data in Java which will introduce you to arrays which are a data structure that's common to many programming languages including Java. After completing this lesson you will recognize common array terminology as well as know what a Java array is and how it works. You will also understand how to create an array and know the default value used to initialize all elements in an array. Finally, you will learn how to write a loop that accesses and processes all elements of an array quickly and efficiently. As discussed in the introductory lecture we want to investigate the ability to store many different values in a single collection. In this lecture we are going to explore Java's arrays. We are starting with arrays since they are the oldest and most common way to store a collection of values and most programming languages support some form of arrays. An array is an object that can store a large collection of values for us as long as all the values are of the same type. And since all these values will be stored in contiguous locations in memory the array has the ability to directly access any one value when given its position in the collection. This array object has only a small number of predefined methods. When first learning about arrays it is easiest to think about them as a collection of variables that are all of the same type. And when we specify the position of any one element in the collection we use zero base indexing in the same way that the characters in a string object use zero base indexing. That is the first element is at index zero the second at index one, et cetera. For example, if we have an array called score that has five elements it is easiest to think about it as a collection of five variables score zero through score four. These five variables all contain data of the same type. We can use these five variables just like any other variable by accessing its current value assigning a new value passing its value to a method, et cetera. Here are some common terminology that we use when discussing arrays. When addressing the entire collection of values we talk about the array. And when discussing a single value in the collection we use the term array element. The index is the position of an array element in the collection the type being stored in the array is known as the base type. And finally we refer to the number of values being stored in the array as its size or length. Since an array is an object type we must declare its variable and create the object in a two step process which is similar to all objects except strings since the compiler knows how to create those for us. The syntax of declaring an array requires that we specify the base type of the array followed by empty square brackets. The base type can be any type including class types. The empty square brackets indicates that we want an array of that type rather than just one variable of that type. We then give the array a name. We then create the array object with a new operation where we specify the base type of the array again and in this case we specify the desired size of the array in the square brackets. Once the array object is created we can then assign it to the array variable. Here is an example we see the declaration in square brackets score gets assigned new int five. This creates an integer array object of five elements and assigns it to the integer array variable score. Note that score is simply declared as an integer array and it can be assigned an integer array of any size. We only need to specify a size when we create the actual array object. The size is required and must be a non-negative integer value. It could be a compile time constant or it could be a value determined at runtime. Once an array of a specified size has been created its size cannot be changed. When an array is created all elements of the array will be initialized to the zero equivalent value for the base type of the array. That means arrays of type int and double are initialized to zero values. Arrays of type boolean are initialized to the value false and arrays of object type, including strings are initialized to the special value null which means there is no object yet. A common way to visualize an array is to draw a row or column of boxes and label each box with its index. The index of the first element is always zero. The index of the last element is always the size of the array minus one. Note that square brackets are used in several different places and in different ways when dealing with arrays. First, we use empty square brackets of what the base type when we declare an array variable. In that case, the square brackets are always empty. Next, we use square brackets with an integer expression when we create an array object. And finally, we use square brackets with an index to access an element of the array. When accessing an array element, we get the single element out of the array at the specified index. Again, arrays use zero base indexing. If we reference the array element in an expression, we will get the current value that that array element is holding. If we specify the array element on the left hand side of an assignment operator, we will give it a new value. We can use these array elements wherever we would use a normal scalar variable as shown in the example code. First, we see how the array looks when it's created. And now we see what it looks like after the code executes. Score one has a value 12, score of two has a value 15, and score four has a value three. The index that you use in an array reference must be an integer value in the range zero up to the length of the array minus one. If the index that you use is invalid, that is less than zero or greater than or equal to the length of the array, then Java will throw an array out of bounds exception that will cause your app to stop. Here are several examples of valid array references and invalid array references. Note here how the index expression can be either a compile time constant or a runtime value, but it must be a valid index value. Given that we can now create an array, we often want to process all the elements of the array. The easiest way to do this is to use a for loop. In the example shown, you use a for loop to iterate over all possible valid indices and print each element of the array out on its own line. We can use the same for loop strategy to assign new values to all elements of an array. Array processing with for loops is easy since the array contains some number of elements and for loops are good when the number of iterations is known. Now there's one additional thing about arrays that makes processing them in for loops easy. Every array object has a data field called length that keeps track of the size of the array. Thus you do not have to remember the size of the array, rather any array can tell you its size by accessing its length field. You can access the length field of any array by using dot notation on the array name. This is slightly different than accessing the length of a string. Since for strings length is a method that requires the parentheses. Whereas for arrays length is a data field and does not use parentheses. Note that this data field is read only and thus you cannot assign a new value to it. This makes sense since we mentioned earlier in the lecture that once an array is created its size is set and cannot be changed. This length field is very handy when writing for loops to process an array as it results in cleaner code. Here's one of the for loops from a previous slide that prints out all the values from the array score. This loop has been changed to use the length field of the array rather than the literal five. Note that this code will continue to work even if the program is changed in the future to use a larger or smaller array. The first part of this lesson introduced you to Java's arrays, which are a common data structure in most programming languages. Now that you have completed this part of the lesson you should recognize common array terminology as well as know what a Java array is and how it works. You should also understand how to create an array and know the default value used to initialize all the array elements. Finally, you should have learned how to write a loop that accesses and processes all elements of an array regardless of how many elements it has. Welcome to the second part of our lesson on Java arrays. After completing this part of the lesson you'll know how Java arrays can be used to solve various types of programming problems. After working through two very different problems you will recognize how Java arrays often make solution strategies simple and straightforward. You will also understand that elements of an array can be accessed and processed sequentially from the front of the array to the end or they can be accessed and processed randomly at any index value in the array. In this lecture, we will look at some simple examples of using arrays. To start off, let's consider the problem that we used to motivate the need for arrays. In this problem, we want to read in a set of scores and compute their average and then we want to report which scores are below the average so that we can give extra help to those students. Without arrays, we would not be able to solve this problem very easily. But now that we know about arrays this problem can be trivially solved. Our solution will follow this strategy. First, we will need to access the data from the user. We then need to create an array to hold all the scores. After creating the array, we will get each score and place it in the array at the next location. As we do this, we will also sum all the scores so that we can compute the average. After summing all the scores, we divide the sum by the number of scores to get an average. And then finally, we can compare each score with the average. We'll consider each of these steps in order. For this problem, we'll assume that the user has entered all scores in a text box and separated them by a blank character. The app framework will provide this string of input as a parameter to our process method. Given this string, we can use methods of the string class to create an array of strings, one element per value entered. We can later convert each string value into the corresponding integer value. Here we see the starting point of our code, which is the process method inside the logic class. This method will receive a string parameter that contains all the scores. The string class has a method called split. They will divide a string into an array of strings where the delimiting character between values is given as a parameter. In this case, it is a blank. Next, we create an integer array of the correct size. The size we need is the same size as the array that was produced by the split method. So we simply get the length of the vowels array and use it to specify the size of the score array. Next, we will need to convert each string value into its corresponding integer value. This is accomplished by using the parse int method from the integer wrapper class. Once we convert the number, we store the value in the next element of the score array. As we do this, we also want to compute the total of all the scores. And we accomplish that with a simple cumulative sum loop using the accumulator variable total. We can finally compute the average by dividing the total by the number of scores and then use a simple for loop to report which scores were less than the average. And here is a sample execution. Given the input string of scores displayed at the top of the slide, the program would produce the output displayed at the bottom of the slide. Here's another interesting problem where arrays make the solution very simple. We want to simulate the rolling of two dice and report the percentage of times each value was rolled. For this problem, we will use an array of integers where each array element is a counter for how many times the corresponding index value was rolled. Each time we roll the dice, we will increment the correct counter. And here is the code of our process method that is the starting point or a code in the logic class. The first thing we do is to find a constant that is the number of rolls we want to perform. The keyword final makes the variable numRolls, a constant that cannot be changed after it has been initialized. Next, we declare our array of counters. Now when we roll two dice, there are 11 possible outcomes, two through 12. So we could declare an array with only 11 elements, but instead we are going to create an array with 13 elements with indices zero through 12. This will allow us to use the result of a roll to directly index into the array. IE, when we roll a 12, we will access the counter at index 12. This greatly simplifies our code at the cost of having two array elements, those at index zero and one that will not be used. The next thing we do is to create a random object with which we can use to generate random numbers. And now we can look at the meat of our simulation. We have a for loop that will iterate the desired number of times. On each iteration of the loop, we simulate the roll of our two dice by generating random values in the range one to six. We then sum the two dice and use that value as an index into our array of counters and we increment the specified counter. After simulating all the rolls, we iterate over the counters for two through 12 and report the percentage of times each was rolled. To compute the percentage, we divide the count by the total number of rolls and multiply that by 100. To ensure that we get floating point division rather than integer division, we perform the multiplication by 100.0 first. And here is the output of our program. The second part of this lesson showed examples of using Java arrays to solve different problems using different solutions. After studying these examples, you should now know how arrays can be utilized to solve a variety of problems and recognize how Java arrays often make solution strategies simple and straightforward. You should also understand how arrays can be accessed and processed sequentially as we did when we processed exam scores one after another or how arrays can be accessed and processed randomly as we did when we incremented counters based upon the roll of two dice. Welcome to the third part of our lesson on Java arrays which focuses on deepening your knowledge of Java arrays by applying them in a wider variety of situations than the two earlier parts of this lesson. After completing this lesson, you will understand the concept of quick array initialization and when it can be utilized. You will also recognize how to pass a Java array as a parameter to a method and how to use an array as the return value of a method. In addition, you will learn about the arrays class in the Java collections framework and become familiar with how its methods can be used to manipulate arrays by sorting, searching, copying, and filling their contents. Finally, you will know how arrays of objects work and why they require a two-step initialization. In this lecture, we are going to continue our exploration of Java arrays by considering topics such as passing arrays as parameters to a method or methods that return arrays to the caller and the arrays class that contains several helper functions. To start with, we will look at quick array initialization. It is possible to create and initialize an array in a single step. Rather than specifying the new operation, you can simply list the values you want the array to have in a comma-separated list inside curly braces. This will create the array and initialize it with the given values in one step. This is very useful when you know at compile time what values you want the array to have. For example, you are creating a string array of seven elements where each element will hold the name of a day of the week, i.e. the first element is the string Sunday and the second is the string Monday, et cetera. Note that when you use this quick initialization that you do not need to specify the array size since the compiler is able to figure it out by counting the supplied values. Next, we will consider passing entire arrays as parameters to a method. To do this, we must declare that the method receives a parameter that is an array type. This is similar to declaring a variable that is an array type. You specify the type of the parameter with empty square brackets after the base type and then you give the parameter a name. Then to call this method, you must apply an array object for the given parameter. You can do this by simply giving the name of an array variable. Note that at the call site, we do not need to use any square brackets. Here's the full code for the snippets given on the previous slide. The method average is an example of a method that takes an integer array as a parameter and the method process contains a call to that method. Note that the parameter declaration does not specify an array length and thus the method average can receive an integer array of any length and compute the average of all the values contained inside the array. Since an array is an object, the called method receives a reference to the object and thus any changes that are made to the array will be seen by the caller when the method returns. This will be discussed in greater detail in a later module when you learn about passing objects to methods. In addition to passing an entire array to a method, a method can return an entire array to its caller. This requires that the method has a return type that is an array type. Again, a type that uses empty square brackets. Then the method must have an array to return. It can either be an array that is created by the method or an array that the method receives as a parameter. And the method simply specifies the array it wants to have return in its return statement. And finally, the caller of the method needs to assign the return value to an array variable of the correct type. Here's an example of a method that returns an array. This method named mirror accepts an integer array as a parameter and returns an integer array that contains all the data from the parameter array in a mirrored fashion. IE, if the parameter array contains the values three, eight, 10 and four, the returned array will contain the values three, eight, 10, four, four, 10, eight and three. Looking at the code, the first thing that the method does is to create a local array that is twice as large as the parameter array. It then copies each element from the parameter array into two elements of the local array. One element offset from the front of the array and the other element offset from the rear of the array, thus creating the desired mirror pattern. And then finally, the entire array is returned to the caller. When using a method that returns an array, you need to assign the return value to an appropriate array variable. For example, if we were to call the mirror method that we defined on the previous slide, we would want to assign the return value to a variable that was declared to be an integer array. In the code that is shown, we assign the return result to the integer array variable named reflection. Note that this code does not perform a new operation to create an array for the variable reflection. And that is because the method mirror performs the new operation for us. As has been mentioned before, arrays are objects. However, they do not have many useful methods available inside the array object themselves. To help addresses, job has the arrays class that contains a collection of static helper methods that operate on arrays. Similar to how the math class has a collection of static helper methods that operate on numbers. Here are a few of the more popular methods from the arrays class. The two string method will return a printable string representation of the array. The equals method will determine if two arrays are identical. The fill method will assign a new value to all the array elements. The sort method will arrange the elements into sorted order. And the binary search method will search an array for a value and return its index if the value is found. Or it will return it negative integer, which is never a valid index, if the value is not found. For binary search to work, the array being searched must already be sorted. The arrays class is located in the Java.util package. And so if you want to use it, you must include an import Java.util.aster statement near the top of your Java file. Let's consider this example that uses a couple of the methods from the arrays class. In this problem, we want to return the median value from a set of numbers, where the median is defined to be the middle number when the numbers have been sorted. To solve this problem, we will first make a copy of the array so that we do not modify the original array. This step could be skipped if the caller does not mind us sorting their array. After making the copy, we will sort the array. We can then easily report the median value, which is the middle value of an odd length array, or the average of the two middle values for an even length array. And here's our method median. There receives an integer array as a parameter and returns a double value. We return a double value since we might be taking the average of two integer values. The method starts by making a copy of the parameter array by calling the copy of method of the arrays class. This method will make a copy of the parameter array with a number of elements specified by the second parameter. In this case, we are making a complete copy of the array named numbers. After the copy has been made, we sort the copy by calling the arrays.sort method. We calculate the midpoint of the array using integer division, and then we determine if the array has an even or odd length. If the length is even, we return the average of the two middle elements. In this case, we divide by 2.0 to get floating point division rather than integer division. If the length is odd, we simply return the middle element of the sorted array. For our final topic on arrays, let's briefly discuss arrays of objects. As mentioned earlier, when an array is created, its elements are initialized to the zero equivalent value for the base type of the array. For arrays of object types, this initialization value is a special value called null. The null value simply means that there is no object yet. For example, if we create an array called coordinate that is an array of three elements of type point, all three elements will be initialized to the value null. Before we can use this array, we need to replace all the null values with actual point objects. Thus, arrays of object type require a two-step initialization. In the first step, you create the array object itself. And then in the second step, you create an object of the base type for each element of the array. In the code sample, after creating the array called coordinate, which is the first step, we then perform the second step in a loop that creates an actual point object for element zero, then element one, and finally element two. We will conclude this lesson by introducing the concept of a multi-dimensional array. So far, all the arrays that we have considered in this class were one-dimensional arrays. But Java also supports multi-dimensional arrays, the simplest being the two-dimensional matrix. But higher-dimension arrays are also possible. When declaring such arrays, each additional pair of square brackets indicates another dimension of the array. Here's an example of a three-dimensional integer array that is three by five by two. We do not have time in this class to go into multi-dimensional arrays other than to tell you that they exist. The third and final part of this lesson focused on deepening your knowledge of Java arrays. Now that you have completed this part of the lesson, you should understand the concept of quick array initialization and when it can be utilized. You should also recognize how to pass a Java array as a parameter to a method and how to use an array as the return value of a method. In addition, you should have learned about the arrays class in the Java Collections Framework and become familiar with the methods it provides to sort, search, copy, and fill the contents of an array. Finally, you should know how arrays of objects work and why they require a two-step initialization. Welcome to our next lesson on structured data in Java, which will deepen your knowledge of Java array traversal via a new control flow construct, the for each loop. After completing this lesson, you will understand how the for each loop can greatly ease access to and processing of arrays. You will also be familiar with the key differences between a normal for loop and a for each loop. Finally, you will recognize the limitations of for each loops and know the cases where a normal for loop must be used instead. In this lesson, we will explore an additional way that Java provides for easily processing arrays and which is also applicable to other Java structures that will hold data for us. So far, when we want to process all the elements of an array, we have written a for loop that iterated over all possible index values from zero up to the length of the array and then use that index to access each element of the array. This is known as an array traversal. You can think of it as walking across the array and processing each element encountered along the way. This is common when we want to print the elements of the array or search the array for a particular item or similar array processing issues. This is such a common task that Java added an additional loop construct just to handle it. It is called the for each loop. It starts with the keyword for, similar to a normal for loop, but what goes inside the parentheses is quite different. Instead of declaring and initializing a loop counter variable, you declare a variable that is the same type as the base type of the array. That is followed by a colon which is then followed by the array name. Then in the loop body, you can use the loop variable you created rather than using an indexed array element. The loop variable will be assigned the next element of the array on each iteration of the loop. Thus, the for each loop is equivalent to this standard for loop where we declare a loop counter variable and have it iterate over all possible index values and then assign the next array element to a local variable which we then use in our calculations. Consider this example where we want to compute the average of all the values contained in an integer array. We saw this example several times already. We declare and initialize our cumulative sum variable before the loop. Then we have a for each loop that gets each value from the array and adds it to the accumulator. Notice how the for each loop greatly simplifies the processing by getting rid of the integer loop counter and subscripted array expressions. When looking at this code that contains a for each loop, you read it as for each integer num in the array numbers do the following. Where in this case, we add that num into the total. Here's another example. In this case, we have an array of integers and we want to report the largest value in the array. We call the method max to find the maximum value for us which we then print out. And here is the method named max that receives an integer array as a parameter. We initialize the variable max so far with the first element of the array and then we use a for each loop that says for each integer num in the array numbers, if num is larger than max so far, then assign num to max so far. When we exit this loop, the variable max so far will hold the largest value in the array and we return that value. Note that the values in the points array represents the points scored by the Golden State Warriors MBA team over their past five games at the time this lecture was recorded. When we compare for loops to for each loops, we find that the standard for loop is always safe and you are free to use it whenever you wish. However, the for each loop can make your code much easier to read by other programmers and so you are encouraged to use it as much as possible. In addition, the for each loop is applicable to other collections in Java where the standard for loop cannot be used. We will investigate these collections in our next few lessons. And because of this, the for each loop is preferred over the standard for loop in most cases. Unfortunately, the for each loop does have some limitations. The for each loop is only good when you want to read the date in the array and thus it cannot be used if you want to change the date in the array. That is because if you assign a new value to the for each variable, you are only changing the for each variable and you are not changing the corresponding element in the array. Additionally, since there is no loop counter variable, you do not know which element of the array you are processing on any given iteration. Thus, if you wanted to return the index of an array element that you are currently processing, you cannot do that. Another limitation of for each loops is that they always process the array in a forward direction and always in single steps. Thus, if you want to process an array in reverse order or in steps other than one, you cannot use the for each loop. And additionally, a for each loop only iterates over a single array and thus it is not the best choice when you have a loop that needs to process two or more arrays at the same time. But these restrictions are minimal since most of the time we are simply traversing a single array, in which case you are highly encouraged to use the for each loop. And even if you do not use the for each loop yourself, you need to be able to recognize and understand it when you see it in code written by others. This lesson deepened your understanding of array processing and traversal in Java. Now that you have completed this lesson, you should be familiar with the concept of array traversal and understand how the Java for each loop can greatly ease access to and processing of arrays. In addition, you should be familiar with the key differences between a normal for loop and a for each loop. Finally, you should recognize the limitations of for each loops and the cases where a normal for loop must be used instead. Welcome to the first part of our next lesson on structured data in Java, which will expand your knowledge of the Java collections framework. After completing this part of the lesson, you will understand the purpose, importance, and benefits of this framework. You will also know how it creates a powerful package of useful and reusable data structures by leveraging various Java features, such as interfaces and generic types that are covered by upcoming modules in the MOOC. Finally, you will recognize the key interfaces defined in the Java collections framework that are implemented by classes we cover in the second part of this lesson. The Java collections framework is a set of interfaces and classes that allows us to store a bunch of data in a single object, similar to how an array can hold a bunch of data for us. But the collection framework gives us so much more than what arrays can, that they are now the go-to mechanism for storage needs by most Java programmers. Even though arrays are great at storing a collection data for us, they have many limitations. The first limitation is that once an array is created, its size is set, and it cannot be changed. Thus, once an array is full, we cannot add any more data to it unless we allocate an entirely new array and copy all the existing data over. One might be tempted to say that well, I'll always allocate an array that is bigger than what I might ever need. But then we have much unused and wasted space if we only have a few data elements to store. Another limitation is that we had to manage exactly where all the data was going to be stored in the array, choosing the index where a data item would be placed when added to the array and explicitly stating where data items would be moved if we had to shuffle data items around in the array. Arrays also did not have many built-in functions that assisted us in managing the data that was stored. And for some applications, arrays simply do not provide an efficient solution. Consider using an array to represent a DNA strand. If we ever cleaved a section of nucleotides from the middle of the strand, we would need to shift all the subsequent data down in the array to fill the vacated elements. And that could be a lot of work if our DNA strands were very long. To address these shortcomings, Java has what is known as the Java Collections Framework. Here, a collection with a capital C can simply be thought of as a container that holds elements of the same type in a single object. In that sense, a collection is similar to an array, but it is how we view the collection and the elements it stores that can vary from how we view an array. We could have a container that holds a list of students that is ordered by their student ID, or we could have a set of playing cards in a card game, or we could have a group of name and phone numbers that allows to map a name to its corresponding number. Notice how these applications are addressed in terms of a list, a set, or a map. And the collection framework does a wonderful job in presenting a unified methodology for storing, retrieving, and manipulating the data regardless of whether we consider the data as a list, a set, or a map. This collections framework has many benefits. First and foremost, it provides us with several standard ways of storing data. This frees the programmer from having to write such support code and dealing with such low level issues, and thus it allows the programmer to concentrate on high level problem solving issues and program functionality. Second, the size of the container is not static, but rather it can grow and shrink as needed while you're using it. And it is all done for you automatically. You can choose a container that is a better fit for the problem you're solving, thus resulting in more efficient code. And you can rest assured that the container that you use has been highly optimized to run quickly. And as we will see later, the framework has its foundation on a set of interfaces that share common methods. This helps in two ways. First, by raising the level of extraction so that we are not worried about implementation details. And second, it allows us to easily move to a different implementation at a later date if we so desire. And finally, any one collection is very easy to learn and your knowledge is applicable to other collections in the framework. To summarize, some programmers consider the collections framework to be the best part of Java since they are elegant, they are uniform, and they are flexible. These allow us, the Java programmer, to be much more productive when writing apps for execution on an Android device. Thus, they are very important for us to understand a bit about how they work and how to use them. This lesson will just cover the basics and we'll have two later lessons that will explore two containers in more detail. Before we get into details, we need to define some terms, some of which will be discussed in more detail in a later module of this class. In Java, a collection is an object that will hold a group of other objects. Note they only hold objects which precludes primitive types. But Java does provide what is known as wrapper classes for our primitive types. And Java defines a framework as a unified architecture for representing and manipulating collections. That simply means that we can treat most collections very similarly, even though they act very differently. Continuing with definitions, Java defines an interface as a set of method headers that do not contain implementations. Since there is no implementation of the methods, we call it an abstract class. It is useful for specifying what methods will be available and how to call them and what they will return, but not how they are actually implemented. And finally, a generic type is a class or an interface that is parameterized. In this case, the parameter is type information, which specifies the type of data that will actually be held in the container. This parameter will receive a type when we create or instantiate an actual container object. Before continuing, let's talk for a moment about the importance of interfaces and generics in terms of the collections framework. When the various containers in the collections framework use the same interface, that means they all supply the same set of basic methods. They may also supply additional methods, but we know at a minimum that all the methods specified in the interface exist. This makes the classes uniform. And once you know how to use one, you know how to use the others as well. And more importantly, you can decide to use one of the other containers without changing your code that operates on that container. Additionally, this allows programmers who are working on different parts of a large system to share structures with each other since they are all using the same common interface. Again, generics are important since they allow us to define a container in a type independent manner while still allowing us to ensure type compatibility at compile time. We will see lots of examples of interfaces and generic classes as we move forward. So once again, a collection is an object that can store data for us. Or it's what we also call a data structure. We will refer to the object stored in the collection as elements. Now some collections maintain their elements in some type of order while others are unordered. Some allow duplicate elements while others do not. A few of the typical operations that we perform on a collection is to add a new element to the collection, to remove an element from the collection, to clear all elements from the collection, to search a collection to see if it contains a specific element and to get the size of the collection. Example implementations found in Java include ArrayLists, LinkLists, HashMaps, and TreeSets. And there are more. We will examine ArrayLists and HashMaps more closely in later lectures. The Java collection framework is contained in the Java Util package. And so to use it you must include the statement import java.util.astric near the top of your program. Now recall that our collections are generic types. Again, this allows the collection to be defined once independent of the type of data to be stored. But it also means that we are required to provide the type of data we are going to store when we construct or instantiate the collection's object. The syntax for creating a collection object is to specify the collection name which is immediately followed by the element type and angle brackets. You then give the object a name and initialize it by constructing the set collection via the new operation, which requires a set of parentheses. For example, we can specify that we want an ArrayList of strings and name it words. And then create the object by specifying that we want a new ArrayList of strings with empty prints and a semicolon. After the object has been created, we can now call any of the methods from the collections interface on it. In the example code, we can see that we can add two strings to the ArrayList called words. Finally, it is time for us to dive into the details just a bit. Though we will not cover everything in great detail, there's just not enough time for that in this lecture. So here is a view of the hierarchy of interfaces in the core collections framework, which is very generic in nature and provides a standard interface to all operations that can be performed. At the top, we have the collection interface, which is just a collection of objects. This interface is often used in declarations and method signatures so that any type of collection can be passed around. The set is a collection interface that cannot take any duplicate elements. A sorted set is an ordered version of the set interface. A list is an ordered collection interface that allows duplicate elements and provides object retrieval based on an integer index. A queue follows the standard first in first out principles and offers a variety of implementations. A map is in its own hierarchy since rather than dealing with a single element type, it supports a collection of key and value pairs and we must specify the type of both. The design of the map does not allow duplicate keys. And finally, a sorted map is a map that maintains its keys in ascending order. The collection interface at the top of the hierarchy specifies that these methods must exist. An add method to add a new element to the collection, the contains method, which will search the collection to see if the parameter object is there. The remove method, which you guessed, removes an object from the collection if it is present. The isEmpty method, which will tell us if the collection is empty or not. The size method will tell us how many elements are in the collection and the iterator method will return an iterator over the elements in the collection. We'll discuss iterators later. Finally, if you plan to use any of the classes in the collections framework, it is important to learn all the methods in the collection interface. The set interface, which extends the collection interface, provides for an unordered collection of elements which does not allow duplicates. Thus, it basically models the mathematical concept of a set. It provides the same methods defined in the collection interface with the added restriction that prevents duplicates. The list interface provides for an ordered sequence of elements. Because it is ordered, the user can access elements by their integer index. The user of this interface has precise control over where in the list an element is inserted. Lists, like Java arrays, use zero-base indexing. Besides providing all the methods of the collection interface, the list interface also provides methods to add or remove an element at a specific index, in which case the other elements in the list will be shifted up to make room for the new element or shifted down to fill the vacated spot. You can set or get an element at a given index. You can search the index for an object from the front or the rear of the list, and you can get a special iterator that allows you to move over the list in both directions. The map interface provides an object that maps keys to values. This interface is not associated with a collection interface as it deals with pairs of element types rather than a single element type. A map cannot contain duplicate keys. Thus, each key can map to at most one value. This is similar to how an array maps an index to a value, except now you can use any object as a key rather than a sequence of integers. Two important methods of a map allow you to add or change a key value pair in the map and to retrieve a value from the map that is associated with a given key. Additionally, maps allow you to retrieve the set of all the keys or a collection of all the values contained in the map. This lecture gave you an introduction to the concept of the collections framework. Next, we'll need to get into how they work and how to use them. We will cover that in the next lecture. This part of the lesson expanded your knowledge of the Java collections framework. Now that you have completed the first part of this lesson, you should understand the purpose, importance, and benefits of this framework. You should also know this framework creates a powerful package of useful reusable data structures by leveraging various Java features such as interfaces and generic types that are covered by upcoming modules in this MOOC. Finally, you should recognize the key interfaces in the Java collections framework that are implemented by classes we cover next in the second part of this lesson. Welcome to the second part of our lesson on structured data in Java, which deepens our exploration of the Java collections framework. The first part of this lesson presented a general overview of the framework focusing on key interfaces it defines. The second part of this lesson focuses on several popular concrete classes that implement interfaces in this framework. After completing this part of the lesson, you will understand the characteristics of different collection implementations so you can choose the most appropriate class for a given problem. You will also know several important generic algorithms that work on various Java collections. Finally, you will recognize the different options available for iterating over all elements of a Java collection. In the last lecture, we discussed interfaces and how they relate to one another. But it's important to remember that an interface, as we defined it, just specifies some methods that must be provided. The interfaces themselves are not working classes that can actually do anything for us. To use an interface, we need a concrete class that actually provides all the methods specified in the interface. The classes are free to contain additional methods too, but at a minimum, they must provide the methods of the interfaces. These classes will still be generic, which allows them to be written once but still store data of any type. And a key aspect of all this is that there are many possible ways to implement a given interface. We might implement an interface by using a resizable array to manage the underlying storage of objects. Or we might use a linked list rather than array. Or we might use a tree structure or a hash table to store the objects. Each of these might be used to implement an interface with their own set of advantages and disadvantages. Here's a table showing some of the possible implementations for the interfaces we have been discussing. We see that there are several options to implement a set, or a list, or a map. We do not have the time in this lesson to go into great detail about all these options. But in the subsequent slides, we will highlight the main differences between resizable arrays and linked lists and between hash tables and binary search trees. It is important to understand their strengths and weaknesses and to think about the trade-offs when selecting an appropriate implementation. Before we can compare a resizable array and a linked list, let's briefly introduce their main concepts. We learned earlier that once an array is allocated, its size is set and cannot be changed. So how can a collection have a resizable array? Well, it can allocate a completely new array when necessary and copy all the data from the old array to the new array. If the array is large, copying all the elements may take some time. Now, a linked list stores a sequence of elements very differently. Rather than storing them in sequential memory locations like an array, a linked list stores each element in its own node. Each node has a link to its predecessor and successor. So when we compare resizable arrays against linked lists, we need to do so when considering the different operations that we may need to perform on them. Consider indexing. Arrays allow us direct access to any element in the array based on its index. That is because arrays store their elements in contiguous memory. But if we want to get to a specific index of a linked list, we need to traverse the list from the beginning. When we attempt to insert or delete an element from the middle of an array, we need to shift the subsequent elements to make room or to fill the gap. But such shifting of elements is not required with linked lists. Since we can link in a new node or unlink an old node very easily. And we need to remember that a resizable array will actually need to resize when it becomes full, whereas linked lists can continue to grow without needing to make full copies of themselves. Before continuing, it should be noted that adding new elements to the end of an array is quick and efficient, at least until it needs to be resized. And if we compare the memory requirements of the two, we see that arrays only need to store the actual elements, whereas a linked list must also use memory for the links in addition to the elements. Next, let's move on to hash tables and binary search trees. First, a hash table is a structure that uses a function called a hash function to convert a key into an index into a table. The goal is to strip the keys randomly over the table where we store the elements associated with a key. Thus, given a key, we can quickly look up and retrieve the element associated with it. These tables need to handle the situation when two distinct keys hash to the same location in the table. This is known as a collision. There are different ways to handle collisions and we will assume that the table handles them for us while still maintaining fast lookup. A binary search tree stores its information in a rooted tree fashion that maintains parent child links. In fact, each parent could have two child links to subtrees. And to facilitate fast searches, the tree is maintained in sorted order with all the elements in the left subtree being smaller than the parent element and all elements in the right subtree being larger than the parent element. This is known as the binary search tree property. Given that hash tables and binary search trees are only used to implement set and map interfaces, we will compare them on the limited operations of sets and maps. In particular, these two interfaces are mostly concerned with three issues. One, adding elements or pairs to the collection. Two, looking up elements or pairs in the collection. And three, processing all the elements or pairs in the collection. In the case of performing an insert or lookup, hash tables give us direct access to an element or key via the hash function. Whereas we need to walk a path from the root to a leaf for a binary search tree. Note that we do not need to traverse the entire tree since we can exploit the binary search tree property. When processing all the elements in a set or a map, a binary search tree allows us to process the elements in sorted order. Whereas with a hash table, the processing is unordered. Please note again that it is important to understand the trade-offs between the different implementations so that you can pick the more appropriate implementation for a problem that you are solving. Once you have selected your implementation class, you should still declare your variables in terms of the interface rather than implementing class. This increases your interoperability with code written by others. And it allows you to change to a different implementation class in the future by only changing a single line of code. For example, if you needed a set of strings and you decided that you want to use a linked hash set implementation, you should declare your collection object to be a set of strings rather than a linked hash set of strings. One final note before moving on. The collections framework also defines several algorithms that can be applied to collections and maps. These algorithms are defined as static methods within the collections class. There are methods for sorting and searching, for shuffling and rotating the elements, for reversing or filling a list, and for finding the min and max elements. To conclude our discussion of the Java collections framework, we want to address the issue of iterating through all the data elements contained in a collection so that we can process each element in some manner. We refer to this as iterating over the collection. There are several ways to accomplish this in Java and we will address three in this lecture. We will consider using indexing for each loops and iterators. If the collection you are using implements the list interface, then you can access elements in the collection based on an index. And the ability to index into a collection allows us to use a standard for loop to access each element. For example, if you create an array list of strings and add elements to the array list, you can use a simple for loop that iterates from i equal to zero up to the size of the array list. And then you can use the get method to access each element by its index. Now this does work, but it is not the preferred way. In fact, this style of programming can be very poor for large linked lists since each get operation must walk the linked list all the way from the first element. A much easier way to iterate over a collection is to use the for each loop. This is the same for each loop that we saw for traversing an array and it works in an identical manner. This is very clean and concise and it is recommended to be used when possible. But there is a limitation for using the for each loop in that they are read only and they do not allow you to modify the collection while you are iterating over it. The third way to iterate over a collection is to use an iterator. An iterator is a mechanism for iterating over a collection in a generic way. All collections contain a method named iterator which returns an iterator object for that collection. This iterator has three methods. The has next method which allows you to test if there is another element in the collection. The next method which allows you to access the next element in the collection and optionally the remove method which allows you to delete from the collection the last element that was accessed. And here is our same example which now uses an iterator. After filling an array with data we call the iterator method that creates an iterator object and we sign it to the variable ITR which is an iterator that returns strings. And then we use a while loop that executes as long as the iterator says that there is another object. And in the loop body we get the next object and print it out. This strategy works very well and even allows us to remove elements from the collection if we desired. Though it is a bit more verbose than using a simple for each loop. The great thing about iterators is that they take care of all the low level details for us and allow us to traverse over a collection regardless of what type of collection it is. Iterators work the same for arrays, linked lists, binary trees and hash tables. This is important since sometimes we do not know the exact implementation that we may be dealing with. But as long as we are dealing with a higher level abstraction such as an iterator the low level details do not matter to us. So as has been mentioned before we want to program to the interface rather than the concrete class. And thus our code will continue to work even if we later choose to use a different concrete class. Finally, it is worth taking a moment to note that the map interface does not provide an iterator. But a map does have two methods that return collections to us and we can easily iterate over them. This second part of the lesson on the Java collections framework introduced you to some concrete classes that implement key interfaces in the framework. Now that you've completed this part of the lesson you should understand the characteristics of different collection implementations to enable you to choose the most appropriate class for a given problem. You should also know several important generic algorithms that work on the various Java collections. Finally, you should understand the different options available for iterating over all elements of a Java collection. Welcome to the next lesson on structured data in Java where we take a closer look at Java collection frameworks ArrayList class which provides a powerful array-like data structure that provides direct indexing of any element. Yet it has the ability to grow as needed while an app is running. After completing this lesson you will understand the key characteristics of an ArrayList and what makes it a useful data structure. You will also know its pros and cons compared to built-in Java arrays. In addition, you will recognize common methods that are available to work on ArrayList objects. Finally, you will learn how an ArrayList can be used in practice via an extended example that we will examine in detail. Now that we have learned the basics about the Java collections framework we are going to take a closer look at the ArrayList class which implements the list interface of the framework. ArrayLists serve the same purpose as arrays in that they store a sequence of same type elements in contiguous memory locations and allow us direct access to any element based upon its index in the sequence. The biggest difference between the two is that ArrayLists allow the size of the collection to grow dynamically while the program is executing whereas the size of an array is set once it has been created. So how does an ArrayList object support direct indexing like an array while still allowing the size to grow? Well, first off, it uses an array as an instance variable inside the object. This array is hidden inside the ArrayList object and the ArrayList object will store its elements in the array. This allows the ArrayList to support direct indexing of its elements. But because the array is hidden inside the ArrayList object the object is free to replace it with a larger array whenever the need arises. It can accomplish this by allocating a new larger array, copying all the data into the new array and then replacing the old array with the new one. And we continue to use zero based indexing with ArrayLists as we did with arrays and strings. Since an ArrayList is storing data in a private array it needs to keep track of two properties. One, the logical size which is the number of elements it is actually storing the array and two, the physical size which is the actual size of the array. Now the size method will tell us the logical size of the ArrayList. Thus we can know how many elements to iterate over if we want to write a for loop. The ArrayList does not have a method to tell us the physical size of the array. But that is okay since we really don't need to know that information. All we need to know is that if we fill up the physical array then the ArrayList object will automatically allocate a new larger array. When an ArrayList is initially created its logical size is zero since it is empty and the object will keep track of its size as elements are added and deleted. When we compare ArrayLists against arrays we have already mentioned that their main selling point is that they can grow or shrink automatically as we add and delete elements from the collection. But there is more than just that. ArrayLists make certain tasks much easier since they take care of many of the details for us. This includes inserting and removing elements from any place in the collection. When we add an element into the middle of a collection the existing elements must be shifted up to make room for the new element. Or when we delete an element from the middle the subsequent elements must be shifted down to fill the vacated spot. ArrayLists handle all of that work for us. Also the ArrayList provides some searching functions that do not exist for arrays which can also make things easier for us depending upon the type of search we're performing. I do want to note that the two are about equal when you need to process all the elements of either an Array or an ArrayList. As in each case you can write a simple for each loop or a standard for them. Well, given all these advantages of an ArrayList why would we ever want to use a plain Array? Why not always use ArrayLists? Well, besides the fact that arrays have been around forever and not all programming languages have ArrayLists there are a few reasons one might still want an Array. First, ArrayLists are a little less efficient than an Array. The difference is not big enough that it would make an impact on most applications but if you are writing some time critical code then you might want to use an Array instead. Second, we lose those nice square brackets that allow us to easily access elements of an Array. With ArrayLists you must use method calls rather than the square brackets. Third, ArrayLists are one dimensional and although creating multi-dimensional ArrayLists is possible it is a bit tricky. And finally, since ArrayLists are a part of the collection framework they only hold class type elements. This is not as big of a problem as it once was as Java now has wrapper classes for integers and doubles that will automatically cover two and from the primitive types int and double. So to summarize there are some reasons why someone may want to stick with an Array over an ArrayList but for most applications an ArrayList is probably the better choice for its ease of use. So besides giving us those convenient square brackets and the length field from which we can tell how big an Array is, ArrayLists do not offer many tools for manipulating them. Rather, we the programmer must write code to explicitly manage the elements of an Array. In comparison, ArrayLists have a group of very helpful methods that can alleviate us from the task of managing all the elements ourselves. We will consider some of the methods in the following slides. First, let's talk about adding new elements to an ArrayList. The add method will handle that for us. There are two versions of this overloaded method. In the first version you simply specify the element you want added and it will be added to the end of the list. In the second version you specify the element and the index where you want it inserted. In this case, all subsequent elements are shifted up to make room for the new element. Note that when you add an element to an ArrayList we always increase the size of the ArrayList by one. Similarly, there are two ways to delete an element from an ArrayList. In the first, you specify the object you want deleted and the first occurrence found will be removed from the ArrayList. In the second, you specify the index of the element to be deleted. In both cases, if there are any elements that follow the one deleted, they will be shifted down to fill the vacated spot and the size of the ArrayList is reduced by one. If you want to retrieve or change an element of the ArrayList, you use the get and set methods respectively. They both require that you specify an index for a currently existing element of the ArrayList. And as has been mentioned before, the size method returns the number of elements currently being held in the ArrayList. And here's a quick summary of some of the main methods of the class. In this table of methods, we have already covered the methods add, get, set, and size. The isEmpty method tells us whether the list is empty or not. The toString method returns a string representation of the elements in the list. The remove methods have been covered. The index of method takes a target value to look for and returns the index of the first occurrence of the target. While last index of returns the index of the last occurrence. Both return a minus one if the target is not found. The contains method returns true if the target parameter is found anywhere in the list. And the containsAll method takes a list of targets as a parameter and checks to see if they all can be found in the ArrayList. The equals method will compare the ArrayList to a parameter list to see if they are equal. That is, they contain the same elements in the same order. The ArrayList class has two methods that can return iterators. One that returns a normal iterator and one that allows us to traverse the list both forward and backward. The clear method will remove all elements of the list and set its size back to zero. That is just some of the methods provided by the ArrayList class. As you can see, these methods make ArrayList so much more powerful than simple arrays. As was discussed in the prior lesson, whenever we create an ArrayList object, we should use the list interface as the type of the variable. For example, if we create an ArrayList of strings, we should assign it to a variable that is declared to be a list of strings. This will allow us to easily change our code in the future to use a link list rather than an ArrayList. If doing so would be beneficial. This is not required, but it is highly recommended. You will understand the reasons for this when you get to module seven of this class. And before we get to our final example, it should be noted that the ArrayList has an alternate constructor, which allows you to specify a desired size for the array that is hidden in the object. This is helpful when you know the approximate number of elements you want to store in the ArrayList, as it will help avoid some resizing steps as elements are added. Note that even if you specify a size, the ArrayList will continue to grow if necessary and that the specified size is just a starting size for the physical array. Finally, let's consider an extended example of using an ArrayList. Consider the game of Hangman. Most of you are likely familiar with the game, but just in case, let's do a quick review. One person thinks of a hidden word and tells the other person the number of letters. The other person then attempts to discover the word by guessing letters one at a time. For each guess, the first person either tells the guesser that the letter was correct and where the letter belongs in the word or the guesser is informed that the letter was a miss. The game is over when all the letters of the word are discovered and the guesser wins or when there are six misses in which case the guesser loses. Now, we are not going to develop a complete Hangman game, but rather we are going to develop a couple of methods that could assist the guesser. In particular, we are going to create an ArrayList that will hold a collection of the possible words for us and then we will write other methods that will remove words that either contain an incorrect letter or that are missing a required letter. We will start by writing a method that will load an ArrayList with a collection of possible words. For this game, we will use the official ScrablePlayer's dictionary. Since reading in all the words from a file is non-trivial on Android and beyond our current skill level, we will assume someone else has read all the words from the file into an array of strings and that array is then given to us. Note that we will not load the entire dictionary from the array into the ArrayList, but rather only those words that are the same length as the hidden word. Using an ArrayList for this task is a good choice since we really don't know how many words we will be loading ahead of time and so it is important that the ArrayList can grow as needed. Let's start discussing the code by examining the method header. The method is called LoadWords and it takes two parameters. One, an integer that represents the length of the hidden word and two, an array of strings containing all the words from the official ScrablePlayer's dictionary. And we see that the method returns a list of strings. In the body of the method, the first thing we do is to create an ArrayList of strings and we assign it to the variable words. Since the official ScrablePlayer's dictionary contains about 80,000 words, we create an ArrayList with an initial physical array of 1,000 elements. We then have a for each loop that processes each word in the parameter array. And for each word, we test to see if it is the same length as the hidden word. If it is the same length, we add it to the ArrayList. When we are done, we return the ArrayList to the caller. Next, let's say the guesser made a guess and is told that they uncovered one of the letters of the hidden word. At this point, we want to remove all the words from the word list that do not have that letter in the given position. We will write a method to do this. The method will take three parameters, the letter that was uncovered, the position of that letter, and the ArrayList. Note that if a guess uncovers two instances of the same letter, we would need to call this method twice, once for each position. And here's the code that will do that. The method is called must have at, since we are requiring that each word must have a letter at a given position. The method takes the three parameters we discussed on the prior slide. In this method, we will be removing the words from the ArrayList. When we do this, all subsequent words get shifted down to fill the vacated entry. This causes problems for us if we were to traverse the list from front to back, since if we advanced to the next element after deleting an item, we would have failed to test the element that just filled the vacated spot. A simple way to address this problem is to traverse the list from back to front. Then when we move to the next element, we will be accessing an element that was not affected by the shifting of data. So looking at the body of the method, we have a for loop that iterates from the last index of the ArrayList at position size of the list minus one, down to index zero. In the for loop, we get the word at that index, and then test to see if it is missing the desired letter in the given position. And if so, we remove it from the list. We have a little extra check as well to make sure the word is long enough to have a letter at that given position. When the method ends, the ArrayList that was received as a parameter has been changed, and the caller will see those changes. Finally, let's say the guesser made a guess and is told that the guest letter does not appear in the hidden word. At this point, we want to remove all the words from the word list that contain that letter. The method to do this will take two parameters, the invalid letter and the ArrayList. When writing this code, we will use an iterator rather than writing our own for loop as an example of an alternate solution strategy. Here is the method must not have, which will remove all words that contain the letter the answer is not allowed to have. We start by creating an iterator that will iterate over all the words in the ArrayList. And while the iterator says we have another word to process, we get that next word. We then search that word for the invalid letter using the index of method. The index of method will return a non-negative value if the letter is found, in which case we remove it from the collection by calling the remove method on the iterator. Notice that for this application, the ArrayList is an excellent choice since it can grow as large as needed when we're adding words and it has the ability to shrink back down as we delete words. And at any point along the way, we can easily print all the words that are still in the ArrayList to see all the remaining possibilities for the hidden word. This lesson took a close look at the ArrayList class from the Java collections framework, which provides a powerful array-like data structure that can grow as needed while the program is running. Now that you have completed this lesson, you should understand the key properties of an ArrayList and what makes it a useful data structure. You should also recognize its pros and cons compared to a Java built-in array. In addition, you should now know common methods that are available in the ArrayList class. Finally, you should have learned how an ArrayList can be used in practice via an extended example that we examined in detail. Welcome to the last lesson on structured data in Java where we take a closer look at the HashMap class, which provides a valuable tool in the Java collections framework that can be applied to a wide range of applications. After completing this lesson, you will understand the key characteristics of a HashMap and what makes it such a useful data structure. You will also know its pros and cons compared to Arrays and ArrayLists. Finally, you will be able to recognize common methods that are available to work on HashMap objects. Now that we have studied the ArrayList class, we are going to take a closer look at the HashMap class, which implements the map interface of the Java collections framework. Before jumping into HashMaps, let's quickly review Arrays and ArrayLists. Arrays and ArrayLists provide us with a super convenient way to store data and it is stored in such a way that we have direct access to any element by using its index. In fact, it is sometimes useful to think of arrays in terms of mapping an integer key to a value. For example, think back to the example of simulating the role in of two dice a bunch of times that was discussed in an earlier lecture. In that example, whenever we rolled the two dice, they produced a value or key which was used to get the associated counter. These concepts make Arrays and ArrayLists very fast and efficient as well as very easy to use, but there are still some problems that just don't lend themselves to being solved with arrays. Often, we encounter problems where our keys are not integers that can be used as an index into Array, but rather we have data of different types that act as our keys. For example, we might want to map names to corresponding phone numbers or we might want to map state abbreviations to state names or possibly map student IDs to the matching student records. Note that in many cases, the keys we are using are no longer integers. And even if the keys are integers, as in the case of the student IDs, the values are too large to be used effectively as an array index because the array would have to be so much larger than the number of records that we actually want to store. Here is where hash maps come to the rescue. The hash map is a part of the Java collections framework and it can be used to solve a large number of problems where arrays and array lists do not provide a good solution. The hash map implements the map interface that is defined in the framework which allows us to create relationships between keys and values. It is important when creating such relationships to ensure that the keys are unique. This guarantees that there is only a single relationship per key. For example, a dictionary is a nice analogy of a map. It maps a key, in this case a word, to an associated value which is the corresponding definition. We see that the keys and their values form a pair which is what gets stored in the map. Whenever you want to get a value from a map, you give it a key and the map returns the associated value. In this view, we see that an array is simply a map that has integers as keys. You provide an array, an integer key or index and you get back the associated value. Hash maps exist in many different programming languages and often go by different names. Some languages such as common list, Perl and Ruby refer to hash maps as hash tables or simply hashes. While other languages such as Python and Objective C refer to them as dictionaries and still other languages call them associative rays. So if you hear those other names used, you can relate them to Java's hash map. A hash map is a structure that uses a function called a hash function to convert a key into an integer index into a table. The goal is to distribute the keys evenly over the table where we store the elements associated with the key. Thus, given a key, we can convert it into an index using the hash function and then quickly insert or retrieve the value associated with it. These tables need to handle the situation where two distinct keys get mapped to the same location in the table. This is known as a collision and there are different ways to handle collisions and we will assume that the tables handle them for us while still maintaining fast insert and fast lookup. A hash map provides several key properties. First and foremost, the ability to use any object as a key and not just integers. As we saw with examples given at the beginning of this lesson, this is a very important property which allows us to use hash maps to solve many different problems with great ease. Additionally, a hash map is very fast and efficient in that we can add a key value pair to the hash map in constant time, regardless of how many items have already been added. And given a key, we can retrieve the associated value in constant time and we can remove a key value pair from the hash map in constant time. These together make a hash map a powerful tool that we can apply when solving different computing problems. With these capabilities do not come free. To be able to have fast insert and retrieval, we do have to sacrifice other capabilities. In particular, we no longer use a convenient integer index to access values, but rather we can only use the keys. Also, hash maps are unordered in that if we iterate over the set of keys, they appear to be in a random order. Thus, if we want to maintain the keys in a sorted order, we cannot use a hash map or we have to supplement the hash map with an additional structure. And finally, if we want to iterate over the set of keys or values in a hash map, it takes time proportional to the capacity of the hash map plus the size of the hash map. Whereas most other containers take time that is proportional just to their size. But in general, these disadvantages make little difference when we are solving a problem for which hash maps are well suited. Next, let's consider the main operations of a hash map, adding, retrieving and deleting information. To add a new key value pair to a hash map, one uses the put method. The put method takes two parameters, the key and its associated value. If the hash map does not have an entry for the specified key, a new entry is created. Whereas if the entry for the key already exists, the new value will replace whatever prior value was there. To retrieve a value from a hash map, one uses the get method. This method takes just a single parameter, the key of the entry we want to look up. And the method returns the associated value. This is similar to using an index to retrieve a value from an array list, but that we use a key rather than an index. If you call the get method and the hash map does not contain an entry for the specified key, the value null is returned. Null is a special reference value, indicating that there is no object being referenced. And deleting a mapping from a hash map is similar to retrieving a value in that you simply supply the key. In this case, the method is named remove and it will delete the entry associated with the given key. Additionally, the remove method returns the value that had been associated with the key. Thus, there is no need to perform a separate call to the get method if you want to know the key value pair that is being deleted. Next, let's look at some of the more common operations that can be performed on a hash map. In this table, we've already discussed the put, get and remove methods that add, retrieve and delete mappings. In addition, there is a size method that reports how many mappings have been added to the hash map. The is empty method reports if the hash map is empty or not. And the to string method returns the printable representation of the map. All of these methods operate in constant time with the exception of the to string method which must necessarily process all the entries in the hash map. There is also an equals method that will determine if another map object contains the same set of entries. The clear method will remove all the entries from a hash map. And the contains key and contains value methods will determine if the hash map has a specified key or a specified value respectively. Note that the contains key method can operate in constant time since we can hash the key to see if it is in the hash map. But the contains value method operates in linear time since we have to iterate over all the values in the map to see if the specified value exists. And there are additional methods that have not been covered here. If you're interested in a full list of available methods for a hash map please see the appropriate reference documentations on the web. Now, if you remember from an earlier lesson the map interface is not considered a collection and thus a hash map is not an instance of a collection since it does not implement the collections interface. As a result, a hash map does not provide for an iterator that allows you to process all the entries in a hash map. Rather, a hash map provides for collection views. These views can allow you access to the set of keys in the hash map or to the collection of values in the hash map. Note that since the keys must be unique we can use a set whereas the values are considered a collection since they may contain duplicates. A hash map has two methods that support these views. The keyset method returns a set view of the keys while the values method returns a collection view of all the values in the hash map. Note that since both of these are types of collections you can create iterators that can process all the data in them. And the key feature of these views is that they provide dynamic access to the hash map in that if you change the hash map you will see those changes in the view and vice versa. For example, if you delete a key while iterating over the keyset the corresponding key value pair will also be deleted from the hash map. For example, say we have a hash map named my map the map string values to integer values and we want to process all the entries of the hash map. We could do so in the following manner. First we call the keyset method on the hash map object my map and assign it to a set of strings. We use a set of strings since the keys are type string. Next we call the iterator method on the set to get an iterator of type string. And then in a loop while the iterator says that we have another element to process we get the next element from the set which will be a string representing a key and then we use that key to access its corresponding value. We can then do whatever we wish with the key and its value. In the code that is given we simply print out the pair. And as with all of our Java collection framework entities it is recommended to declare the object to be of the interface type rather than the implementation type. In this case we would want to declare our hash map object to be of type map rather than hash map since that allows us to easily change to a different implementation in the future if we decide to do so. Again it is not wrong to declare your object to be type hash map just not recommended. There are a few requirements that we must obey when using hash maps. First as is true for all our collection framework structures the data values we deal with must be class type. This requirement means that we have to use the wrapper classes for the primitive types. Additionally, whatever type we use for the keys must have two methods defined for that class of objects. The equals method which can be used to tell us if we have the same key and the hash code method which implements the hash function for mapping an object into an index which can be used in accessing the table. These two methods exist in most classes that Java provides us that we might use as keys in particular the string class. And finally it is highly recommended that the type you use for the keys produces immutable objects. Now this is not a hard requirement but it is recommended since if you put a key value pair into a hash map and later change the key you will no longer find the pair when you attempt to retrieve it. This is because the pair was stored based on the old key but the lookup is being performed on the new key. Let us conclude with a sample problem. In computing we are often interested in counting things. Now if the things we are counting are numbers in a small finite range then it is easy to use an array of counters. Similar to the example we saw in an earlier module where we were counting the number of times each roll occurred when rolling two dice. Other times we are counting things for which we cannot use an array. In that case we can use a hash map to create a mapping from the objects we are counting to a counter associated with that object. Each time we encounter another instance of the object we increment the associated counter in the hash map. For example, let's consider the problem of counting the occurrences of words in a file. In this case we will create a hash map that maps strings to integers where the strings are the words we are counting and the integers are the counters for each word. Since file processing on Android is beyond our current skills we will assume that all the words from the file have already been read in and placed in an array list and our task will be to simply process the words in the array list. We are now going to step through the code to accomplish this task. Again, we are given an array list of strings called words that we wish to count. The first thing we do is to create a hash map that maps strings to integers. We give it the name counts. Next we want to process all the words in the array list. The easiest way to do this is with a for each loop and so we write the code that says for each string word in the array list of words do the following. The first thing we do is to convert the word to lower case so that our counting is case insensitive. Next we determine if the hash map already contains the current word as a key or not. If the current word is not in the hash map we add the word to the map with a count of one. Otherwise we get the current count of the word from the hash map, add one to it and then update the hash map with the new count. Simple, sweet and it works. At words we could use the code presented earlier in this lesson to print out all the words and their associated counts. This lesson took a close look at the hash map class from the Java collections framework which provides a valuable tool for mapping objects one type called keys to objects of another type called values. Now that you have completed this lesson you should understand the key characteristics of a hash map and what makes it such a useful data structure. You should also know it's pros and cons compared to built in Java arrays as well as array lists. Finally you should be able to recognize common methods that are available to work on hash map objects. We have now completed the module on storing and processing structured data in Java. The material covered by the lessons in this module have added several handy tools to your Java programming toolbox making you a more capable developer of Java apps on Android. The tools we studied allow you to store and manipulate data in different ways each with its own pros and cons. As your programming skills grow and mature you will be capable of picking the most appropriate constructs to address the programming problems you are solving so that you can create correct and maintainable code. With that in mind, let's move on to the next module in this MOOC where you will learn how to create your own classes and objects. Welcome to the next module in our MOOC on Java for Android which begins our coverage of classes and objects. The topics covered in this module are essential to developing object-oriented programs in Java. Since there are multiple lessons in this module we first present a brief overview of the path we take to teach you how to use classes and objects effectively. In lesson two we will review the larger concepts of classes and objects that were first mentioned in the MOOC overview but put a decidedly Java spin on them. We will use the string class that you already are familiar with to illustrate some of our examples. In lesson three of this module you will begin to build your own class file and a client file that uses the class. There will be additional resources provided with this lesson so that you can program an Android Studio as you follow along with the video. At the end of lesson three we actually leave you with a broken file one that no longer compiles but in lesson four we'll learn more about how classes and objects are constructed so that we can restore our files and make them better. In lesson five we add more functionality to your class file and begin to appreciate code readability. In lesson six you will understand how to use classes and objects in some familiar constructs like arrays. And finally in lesson seven we wrap up with a brief discussion on generics. If you're willing to put in some time do the work and really strive to understand what is included in this module. You will enjoy the ride. So start your engines and let's get going. Welcome to the next lesson in the module on classes in Java. In this lesson I introduce you to some examples to motivate the purpose of classes and objects as powerful constructs in object oriented programming. After completing this lesson you should understand the need for classes and objects and be able to distinguish between them know how to apply the term abstraction to real world programming scenarios and recognize the two major components of a class which are explained in the context of Java strings. So let's start with this lesson. We are able to model many things using simple primitive data types. Integers can represent counts. A double the cost of something. Characters may represent the days of the week and Boolean values can tell us the state of some condition as true or false. But how could you use these primitive data types to model a student, a shape, a city or a chessboard? That doesn't seem too difficult. Take for example a city. We could create string variables and doubles to represent the name, latitude, longitude, country and population. Five variables could represent a single city. But what if we need to represent several cities or an array of cities? The variables begin piling up and our code becomes chaotic. We need a data type that can represent a city, all of the aspects of a city. We also need to consider the methods used with a city and keep them separate from methods that have nothing to do with our city. Let's take a look at object oriented programming for a solution. Object oriented programming can be thought of as an approach to problem solving. Java is a language specifically written to facilitate object oriented programming. An object in the contents we are using here is the encapsulation of both data and behavior into a single container or object, which can then be used to represent or model something in the real world. Object oriented programming uses objects to perform most of its interactions. You'll soon see that this is very different from programs that use only primitive data types and methods to perform actions. These objects will allow us to model a much more complex world while still keeping this complexity manageable. A wonderful side effect of creating and using objects is something we call abstraction. And we've all encountered this many times. Take a car for example. Many of us would claim that we know how a car works. We can start a car, make it go forward, backwards, and stop. Some of you may even know how to change the oil in a car or fix a flat tire. But if something went wrong with the engine, if the car suddenly stopped working, I dare say that most of us would be at a loss. This is where our knowledge of how a car works comes to an end. We are operating under abstraction here. We know enough about how a car works to make it work for us. Beyond that, many of us will rely on someone else to get the car going again. But this doesn't seem to stop us from owning and operating cars. It's the same with objects. If we can understand them enough to use them, then they have served their purpose. As an Android programmer, you will end up writing your own descriptions of objects that others will use without ever having to fully understand their implementation. We've already used the term class to refer to the file you create when you're writing a Java program. The term class- The iterators. So be used to describe the template for an object, such as a city, student, or chessboard. An object is then an instance of a class. Game three, for example, might be an instance of a chessboard. Let's review the string class. This is a class that is already included in the Java language and enables you to use string objects without knowing all the details about how they work. The string class refers to the file that contains all of the implementation details of a string. A string object is an instance of a string, such as the string apple. A string is a sequence of characters. The variable string one points to, or references, the string object, ABCD. This is different from the primitive data type int. In the memory location referenced by the variable num, we will actually find the representation of the number 23 in binary. In the memory location referenced by the variable string one, we find a reference to yet another location in memory where the string ABCD is actually stored. But there are still some similarities between objects and primitive data types. For example, we can print a string in much the same way that we print an integer. String literals can be assigned to variables and variables can be used to reference their contents. In the case of a string object, we can even use the plus symbol. When it is applied to strings, the plus symbol concatenates the two operands to form a new string. But this is where the similarities end. Recall that one of the characteristics of an object is that both the data that represents that object and the methods used on or by the object are grouped together. Once a string is assigned a variable, we can use string methods to interact with that value. We can concatenate another string with our string. We can extract part of the string and we can print the string contents. Let's take a closer look at how a method is called on an object. Notice the name of the object, in this case a string, comes first, followed by a period or dot. Then we have the name of the method, followed by parameters if they're necessary for that method. Otherwise, empty parentheses would be used. We need to pay attention to what is being returned in each of these methods. For example, the concat method does not change the original string, it returns a new string. We need to either assign the returned string to a variable or print out the results. Here are a few other commonly used string methods. Some string will return a new string. Starts with returns a Boolean value of true or false. Length returns an integer. In each case, we must somehow preserve the returning value. Comparing objects is also very different from comparing primitive data types. We should never use the double equals to compare the contents of two objects. The program will compile and run, but you won't always get the results you expect. Instead, we use a method specifically designed to compare objects, called the equals method. Why is this the case? Well, to fully understand that, we should build our own class file and get a good look at what's going on behind the scenes. This concludes our introduction to classes in Java. In this lesson, you began to build your object-oriented vocabulary with these first few concepts, class, object, and abstraction. Now that you've completed this lesson, you should understand the need for and differences between classes and objects, as well as to be able to distinguish between a variable that can be represented as a primitive data type, such as an int, car, or Boolean, versus a more advanced object that has both state and behavior, such as Java strings. You should also know how to apply the term abstraction to real-world programming scenarios and recognize the two major components of a class. By peeling back a layer of abstraction, we have seen how the already familiar string class works and how it differs from primitive data types. Before moving on, I encourage you to try the self-assessment quiz included with this lesson to be sure you are building a firm foundation. We have a lot more to go in this module on classes, so let's continue with another lesson. Welcome to the next lesson in the module on classes in Java. It's time for us to get started building our own class, now that you have begun building your object-oriented vocabulary and learned more about the Java string class. After completing this lesson, you will understand how to employ the proper syntax for writing a class. You will also know how to instantiate objects from that class file and enhance your knowledge of object-oriented vocabulary by recognizing key terms like state, field, and instance variable, and by knowing how these terms apply to classes and objects. Finally, you'll be able to distinguish between three key roles, class author, client developer, and the end user, and be able to make design decisions based on your current task. This lesson will be greatly enhanced if you open up Android Studio and follow along to create the class with me. Be sure to download the files and pause the lesson when I tell you so that you can modify the code and run it for yourself. Actually, seeing the results and problems that can arise when working with class files will stick with you when you begin to work on your own programs. For this lesson, I encourage you to download the project that accompanies this video and follow along using Android Studio. I will explain more about these files as we go along. You will be making changes to these files as well. Recall that an object is made up of both state and behavior. In this lesson, we will be building the account class. To keep it simple, our account will contain a name, account number, and balance. The behaviors will consist of balance, inquiry, deposit, and withdrawal. When we begin working on the account Java file, we are building the class, the template from which the objects themselves will be constructed. Very often the terms class and object are used interchangeably, but keep in mind the difference. The class is the blueprint, the object is the instance of the class, the realization of that blueprint. Let's start by looking at the syntax for building the instance variables of the class file. The data portion of the class is sometimes called the state because it describes the object, its current condition. Each piece of data is called a field or instance variable. And you can see how together these fields describe the object. Move to the account file, that's the class file. We will create three instance variables, a string, an int, and a double. Notice these variables are not created inside any particular method, as we've done them past. And there is no main module to start with. Keep in mind we are creating a class file. It won't execute on its own. It will contain the information necessary to create account objects in other files that may wish to use them. Now let's look at the behavior of the class, the methods needed to interact with the account class. Start with display balance and deposit. In each case, these methods will need to use data stored in the instance variables. Don't redefine these variables, simply refer to them in your method. Because they are part of the same class, the methods can see these fields. Pause this video if you need to and write these two methods in the account file. Your account file should look something like this with fields or instance variables at the beginning of the file, not contained within any method. Then the methods or behaviors of the class. Let's think a bit about the withdrawal method. At first glance, it should probably be written a lot like deposit. Take the double parameter and modify the current balance. But there could be problems. We need to check and be sure there are sufficient funds for the withdrawal. That's easy enough. But now we have created two possible outcomes for a withdrawal. Either the balance will be modified or the withdrawal will be rejected. This information needs to be provided to the user. Your first response might be an output statement of either the new balance or something like insufficient funds. But step back and consider class and client programs. As the author of the class, you should aim to make your objects useful but also general so that they can be used again in many different client files. This very simple account class for example could be beefed up for security and used by a bank or added on to and used by a game to keep track of online credits or it could become part of another class and used by say a hotel. Most importantly, we need to think of users of the class as other programmers. This is somewhat different from the point of view of the client program author. When writing the client program, which we will do later in this lesson, we use the class and think of users as people who know nothing about the program and how it was created or how it actually works. Right now we are the author of the class and yes, in both cases, we are employing abstraction. Today you are the author of both files so we will need to consider each point of view. What does all of this have to do with our withdrawal method? Well, we were trying to decide what kind of feedback the class file should supply to other client programs. What would other programmers need to know? A Boolean return value is a good choice. One programmer may use the Boolean value to generate one or two screens with messages and other options for their users. Another programmer may use the Boolean value to penalize the game player for attempting to make a withdrawal without sufficient game credits. But you can see that we should leave user feedback to the author of the client program. Pause this lesson now and write a withdrawal method for your account class file. Here is my completed account class file so far. You can't run this file. We'll need a client file to do that. Let's make sure you understand the difference between all of the components we are working with. We just finished working with account.java. That is the class file, the blueprint. We're now going to look at the syntax in the account client program. This is a program that will use our class. The client program will instantiate or create several account objects by calling on the account.java class file. Pause this lesson and run the account client file in Android Studio. We now have a good class file and a client file that uses the class, but we need to make a few more improvements. Notice how the clients outside programs have direct access to instance variables of this class. This is a bad practice. Most, if not all, instance variables of a class should be labeled as private and only accessible to the object itself. At first glance this might seem to create problems, but it is a sound practice. Crontrary to what you may think, you don't have direct access to your own balance at your bank. You may make deposits, withdrawals, transfers, and balance inquiries, but you do this through methods, methods that check for sufficient funds, possibly check some account holder information for security reasons. Checking that, in fact, currency or a valid check accompanies a deposit request. Once again, you are a player in the game of abstraction. If you, or someone less scrupulous than you, did have access to their bank balance, they may change their balance whenever they feel like it, and that's no way to run a bank. By making instance variables private, you are protecting your data. Not in the sense of foolproof security, but that other programmers, those writing clients' programs, for example, will need to think about how to access this data. They will need to make design decisions, and many will then add a layer of real security, such as passwords or encryptions. By not allowing instance variables to be accessed directly, you control how data will be modified and accessed through well-designed methods in your class. In the case of our account class, that means adding some sort of check before a withdrawal is allowed. So what did we learn from all this? Instance variables and even methods that are only used by the class itself should be private. Pause this lesson. Declare all of the account fields as private, and then run the account client program again. Trouble, right? Now that we are protecting access to our fields by using private, code like this, any account program won't work anymore. In our next lesson, we will further improve our class file by adding methods that allow careful access to field variables, and we will learn about constructors, methods that build our objects. Now that you've completed this lesson, you should understand the proper syntax for writing your own class file and know how to use it to create objects that are instantiated in a client program. You should also have enhanced your knowledge of object-oriented vocabulary by learning concepts such as state, field, and instance variable. Finally, by distinguishing between the roles of class designer and client program designer, you should be able to produce classes that can be reused to solve problems in a range of different contexts. As I'm sure you've noticed, we've also broken our programs by using the keyword private and rendering our client program unusable. Therefore, if you'd like to work on your program some more, before you return to the next lesson, open up Android Studio and just remove the private keyword from the fields so your client program will compile and run. You can also add method calls and modify data stored in the fields. Be sure to replace the private modifiers and save your files before starting the next lesson. We will return to these files and continue improving them in upcoming lessons. Welcome to our next lesson in the module on classes in Java, where we continue to refine the account class files and objects we created in the previous lesson and polishing our implementation. After completing this lesson, you'll understand how to apply abstraction principles to hide low-level implementation details from client programmers. By creating accessor and mutator methods, your clients can use to interact with the class. You will also know how to create our own constructors, which will streamline the creation of objects in client files. To begin this lesson, be sure you have launched Android Studio and open up both the client program and the class file. When we left our account client program, it wasn't working. We hadn't made any changes to that file, but we had made changes to the account class file, a file that our client program was using. Making instance variables in a class private is a good practice, but now we need to modify the rest of our class to accommodate these changes. We see two types of methods in a class, accessors and mutators. Accessor methods are used to access data from outside the object. Usually, they are very simple methods that return a value. Mutator methods are methods that change or mutate the value of a field. The method may simply overwrite the variable with some new value. These are often called set methods. It could be something more complex, though, like our withdrawal method that performs certain checks and changes data in some way. Here are some examples of calls and codes for both types of methods. This code may be found in a client method. This is how we should now access a field like name. Here are two mutator method calls you might see in a client program. The first one is simply writing over the value. This is a typical set method. The second mutator will change the value using addition. Code for a simple get method is shown here. This is the kind of method we need to add to our account class for each of the fields we have just created as private. Code for the set method is also very basic, while code for other mutators may contain some very complex tasks. Pause this lesson now and update your account class to reflect some of what we have learned here. Add accessor methods for all of our fields, but only add mutator methods for name and number. We may allow accounts to be reassigned, but we still don't want users overwriting their own balances directly. Your client program should look something like this. Notice how we are creating an object, then filling in the fields. We can combine these two operations into a third type of method used in a class file, the constructor. Constructors are used to create new objects from class files, and you've already been using one, the default constructor. We usually create an object in one line, beginning with the name of the class for which we are creating an object, then the object name, followed by the keyword new, and a call to the constructor method. Notice that the name of the constructor method is always the same as the name of the class itself, but the constructor method is followed by parentheses, like all methods are. Creating an object really takes two phases, which can be seen better here, where we have opted to use two lines of code to create the object. The first line of code creates the reference to the object, but in actuality, no object has been created in memory yet. The second phase creates the new account object and causes the variable to point to it. Notice also, this object's fields are all set to default values. Our client file uses this default constructor, but we never wrote it in our account class. That's one of the reasons it's called the default constructor. It is created by default. We don't need to do anything. It comes free with the creation of the class. We can also build our own constructors, however. A constructor can have input parameters. These parameters can then be used to initialize some or all of the fields as the object is being created. But there is a caution. Once you begin writing constructors of your own, the default constructor goes away. If you want it, you're going to have to rewrite it for yourself, along with other constructors. Here is the syntax for two different constructors. The first one would be used to create an account and set the name and number. Since we didn't initialize the balance, that would still be set to the default value of 0.0. The second constructor will initialize all three instance variables. All constructors must have the same name as the class itself. They are usually public and they never have a return value. This is how we can recognize them as constructors. Calls to these methods would look like this. Notice that both constructors have the same name but different parameter lists. This is an example of overloading a method. The compiler will recognize which constructor you are calling by the parameter list. Pause this lesson and add two new constructors to the account class file. One that sets just the name and number field, and another that sets all three fields. Each will use their input parameter lists as the source for the data. Once they are written, take a look at your account client program. Can you figure out what's going on here? Your account class file should look something like this. But what's causing the errors in the client program? We are still using default constructors, but recall that constructor doesn't exist anymore, not since we started writing constructors of our own. There are two fixes for this. Rewrite the default constructor in your class file, or use the new constructors to set variables while you're creating the object itself. Pause here and modify the account client program. We will forgo writing the default constructor for now, and instead use the new constructors in our client program. This should remove all of the errors from your client program, and it should run again. Writing a class file and a program file at the same time can be maddening. Without making any changes to a client program, errors can suddenly pop up. This is often due to some change made in the class file that now requires a change in the way that class file is used. But it won't always be this way. You may find yourself writing classes to be used by other programmers. Or you may be writing a client program that uses a well-developed class, one that isn't expected to undergo changes while you are writing the client program. In all these cases, you should begin to see how important it is to take some time to plan your design before you dive in and begin programming. In this lesson, we are designing as we go so that these errors will be created purposely. Creating and resolving these errors for yourself is not only a good way to learn about classes in Java, but it should help you to gain a deeper understanding of why the code works the way it does. It's time to start taking advantage of code that has already been written. Here is a good example. Notice that assigning values to name and number is done in both constructors. We should save some coding by starting out with the first constructor and then simply adding on the code to initialize the balance. Here is how we can do that. To refer to a constructor in our own class, we use the keyword this. Let's take a closer look at what's going on here. The client makes a call to the desired constructor. In this case, the constructor that will initialize all three fields. The data from the parameter list is passed to that constructor. The name and number data is then passed to another constructor, which will create the object and set the two fields. Then, the originally called constructor continues by initializing the balance. There is a rule concerning calling one constructor from another, but if we can understand what's going on, it is a rule we can understand and therefore we won't need to memorize. When we call another constructor, we are in essence passing off the work of building an object to the called constructor. Here we see the object is created and variables are initialized. Then any other code from the originally called constructor is executed using this newly created object. For this reason, the call to another constructor must always come first. Trying it in a different order doesn't really make sense now that you know what's going on. If we attempt to initialize the balance field first, then the object must necessarily be created. When we call another constructor to do the rest of the initialization work, that constructor attempts to create an object as it was designed to do. This would cause all sorts of problems. Luckily, this code ordering would also cause a compile error in your class file. Now that you understand why this ordering is done in this way, you won't soon forget it. Now that you've completed this lesson, you should have a good understanding of not only how to create mutator and accessor methods, but why they are fundamental to the good design of classes in Java. We remove the details of the object from the view of the object user. As long as a client programmer who is planning on using our class knows how to interact with the objects of our class through methods, there is no need to reveal the low-level implementation details, which are likely to change over time. You should also know the ins and outs of creating constructors, such as being able to access the type of constructors you need for a class and to write it in Java. Although we've covered a lot about classes, we still have more lessons to go. To make sure you are ready to move on to the next lesson, I therefore encourage you to do several other things, such as taking the practice quiz and working with the account program to write some constructors and add a field to your class. As you do these things, try to get a better understanding of the relationship between the classes, instantiated objects, and client programs. Welcome to the next lesson in the module on classes in Java, where we continue refining our class file and polishing our implementation. After completing this lesson, you will be able to recognize the different uses of the this keyword and use it to make your code not only correct, but more readable. You will also know how to apply two more methods commonly used on objects, to string and equals, and be able to create definitions for these methods that are suitable for your class. Once again, I encourage you to open your account and client programs in Android Studio and follow along with me as we work through the lesson. As we discussed at the outset of this module, there's a lot to learn about classes, so I encourage you not to move ahead without being confident in what we have covered so far. Reviewing videos, taking practice quizzes, and working with the files themselves are all good ways to reinforce the concepts found in this module. When we finished the previous lesson, we saw the use of the keyword this to refer to the class itself, and we also discovered that using this required some knowledge about the underlying details of how objects are created. When we use the keyword this, what we are saying is, in this object, use one of the constructors. Here, this is referring to the calling object, the implicit parameter. Let's look at the keyword this a little bit more. What else can it be used for? Here is another use. The account class has instance variables called name and number, but we may also use some of these same variable names as parameters or local variables in a method. To distinguish between them, we use the keyword this. We call this shadowing using the same variable name from a field variable as a parameter or local variable. It makes the program more readable and allows us to use meaningful variable names. If you find this confusing, simply stick to using different variable names. Another use for the keyword this is when calling another method within the same object. Here, we have a method update balance that uses another method calc interest to do some of the work. We've seen these sorts of arrangements before, methods calling programs. When you're calling a method within the same class, it may be helpful to use the keyword this to emphasize that you are using one of your own methods. Notice also that we made the helper method calc interest private because it will not be used by other clients only by the objects themselves. It doesn't need to be accessible outside of the object. To review, this refers to the implicit parameter, the object on which a method is called. Common uses for this include to call one constructor from another constructor to refer to an instance variable, often optional, or to call another method within the class. Also optional. Let's finish this lesson with two useful methods you will usually create within a class file string and equals. We'll start with two string. Back in your account file add a line to print one of your objects. Run the program. What is this output? When you print an object by including it in a line of output you are implicitly calling the current to string method. That is, you're using it without actually spelling it out. And once again, since we didn't create any to string method yet we are using the default. The default definition for the method to string for any object is to print out the name of the object, the at symbol, and the hexadecimal representation of the memory location where the object is stored. It's an accurate method, but for most of us it's not going to be very useful. We can print a more useful string, but this is cumbersome every time we want to print out an account object. The common practice is to override the default definition of the to string method in the class file and make it more suitable for your object. To create our own definition of the method we define it in the class file. The name spelling capitalization return type and empty parameter list must be the same in order to override this method. For our account class we might write something like this. To use the method in the client program just print an object like you would any primitive data type. Now the output is much better. You could also call the to string method explicitly but that is rarely done. Also notice I've used this here with one of the instance variables to show you how this method is optional but can make your code more readable. Now we will look at the equals method. This is another method that has a default definition. If you don't write a definition for equals in your class file the default method will be used. It will act just like the double equals which we've already warned you against using. If you truly are interested in how this default method works and why there are some cases that double equals does work wait until the lesson new objects in old places coming up later in this module but in almost all cases you're going to want to override the default equals method. Understanding what the default method does isn't critical in this course but will help you to better understand what's going on. To design your own equals method for the class you will need to decide what it means for two of your objects to be equal. It may be that you want all fields to be the same or maybe only a few of your fields need to be the same. Perhaps you want some numeric data to be within a certain range of the other object whatever the case you'll need to be able to write the conditional statements to describe equals and note that to override this method it must be spelled the same way with a Boolean return type for true and false and the input parameter must be an object. Let's take a look. Your object will call this method using another object as the input parameter. First we will need to see if the object that is the input parameter is the same type of object as the object that made the call. In our case we would want to make sure we are looking at another account object. If we are then make the necessary comparisons to determine the equality according to your design. If it turned out that we weren't even looking at the same type of object then we shouldn't even attempt to make the other comparisons. Simply return false. An account object will never be equal to a chessboard object for example. Here is the syntax for the method definition. This would be in the account file. This method will accept any type of object for comparison. But the first thing we need to do is see if this is even an account object. For this we use the instance of keyword. If this is an account then we wish to continue by accessing the number field. But we can't do that with the variable other because other is a type object at least as far as it knows right now. Using instance of we realized that this is an account object so we need to cast it as an account so that we can go ahead and access or refer to its field variables. This would cause an error if we attempted to access for example other.number. Another thing to notice, we can directly access the fields of another account object from any method written in the class file even though the fields may be private. We've covered a lot in this lesson so let's quickly reveal. A class file should contain constructors. Every class will have a default constructor as long as no other constructors have been written. Once you begin writing constructors you'll need to write a default if you want to use it. Every class will have accessor methods. The instance variables or fields of the class should almost always be private so we need accessor methods to allow users of the class to access or examine these variables. Classes should also have mutators, methods that allow users to make changes to some fields. Some may simply overwrite values while other mutator methods may actually perform checks before changing data. That's a string method has a default definition but we saw that it wasn't very useful and that in most cases we will be overriding this method with our own definition. Overriding methods requires that we keep the same name return type and parameter list. A to string method will return a string that is the desired data formatted in a more user friendly way. Finally, the equals method is usually overwritten and makes it possible to compare two objects of any type. If we discover that two objects are of the same type, the designer of the class can then check for other conditions before declaring them equal or not. It took several lessons but we have a working class file and client file that demonstrates the many powerful features and benefits of using classes and objects to create object oriented programs in Java. Now that you've completed this lesson, you should be able to recognize the different uses of the this keyword and know how to write definitions for the to string and equals methods for a class. As you move forward in this MOOC, here are some points to consider. First, learning the syntax of class files, how to instantiate objects and the proper way to call methods associated with objects is only a starting point. More advanced skills such as designing classes that are easily reused by other client programs and identifying what classes may be needed to construct an app will take some time to develop. You can cultivate your own style of object oriented programming by building lots of apps and reviewing apps built by others. There's a lot more we can do with classes and objects, so let's continue in the next lesson. Welcome to the next lesson in the module on classes in Java. I call this lesson New Objects in Old Places because we are going to revisit a few concepts you are already familiar with and see how these notions apply to objects. For example, you are already familiar with arrays of primitive data types, but after you complete this lesson, you'll know how to create an array of objects. You'll also learn what happens when using the equals operator with objects and recognize what happens when objects are passed as parameters to methods. Finally, you'll understand the static keyword. At the conclusion of this lesson you will have deepened your understanding of classes and objects so that you are able to evaluate and determine how objects are used in familiar situations. Let's start by seeing how objects operate as part of an array. Once again, there are similarities between primitive data types and objects. We declare an array of primitive data types, such as int, the same way we would create an array of count objects. But again, we must rely on our new understanding of objects to keep us out of trouble. This first declaration creates an array of variables that will store ints. The second declaration declares an array of variables that will reference objects. We can immediately begin using the array elements of an int array. But if we attempt to access the objects in our array, well actually there aren't any objects in our array, just variables that can reference objects. Creating an array of objects is a two phase process. The first line will create the array of references. Then we often use a for loop to create the objects where the field data will be stored. Then, the data itself can be referenced. We just need to use constructors to create the objects to be referenced. We can create an array of objects using a single line of code, similar to the way we create and fill an int array. This code will create the array of the objects it references. And this code will create the object and fill them with data. Here we use two different constructors that accept parameters for the fields. What about using elements of these arrays with methods? Once you have properly created the array and instantiated each element, they are used and referenced the same as you would any other object. They can call their own instance methods, can be used as parameters and can be printed using the default or overridden to string method. Let's examine an object as a parameter. Once again, we should rely on our understanding of objects. Let's review a primitive data type such as ints first. As a side note, these diagrams are all abstractions that help us to understand how objects work without having to know absolutely all of the implementation details. When a method is called and an int is passed, what we actually pass is the value of that variable. The method may make changes to that value, but unless it is returned to the original variable, no change is seen or made to that original value. What happens when an object is passed as a parameter to a method? A method in a client program, for example. We actually pass the reference to the object. This is known as passed by reference. The method can now access the actual object. If this method happens to change some value in the object, the change will be made to the object itself, not some copy of the object. When the method ends, and the local variables are no longer accessible, the change to the object remains. This is very different from what goes on with primitive data types. Here is a common error seen when working with objects. This is a trap that you should easily avoid because you understand objects and how they work. We have an object that is passed to a method as a parameter. As before, this sets up a reference back to the original object. In the method, we create a new object and fill it with data that is copied from the original object. Then we make the desired change to the balance. And finally, we make the past object equal to the new object in hopes of making the balance change permanent. But the result is probably not what the programmer had intended. The local object X now references the new object. And when the method ends, it all goes away. Notice no change to the original. The lesson? Keep it simple. Pass the reference to the object and make changes using that reference variable. One of the problems with the last example was trying to copy the data of one object to another using the equals operator. Although this works perfectly well for primitive data types, it's quite different for objects. Here we have two objects, account X and account Y. When we make one equal to the other, the effect is as it should be. They both now point to the same object. As it should be, but perhaps not understood by uninformed programmers. Now a change to account Y will also be made to account X, because in fact they are the same object, or they're referring to the same object. This will mystify the less informed, but not us. Setting one object equal to another is permissible in object-oriented programming, but be sure that is exactly what you want to do. If you really wanted to make a copy of an object, there are lots of ways to do it. Here's one way, in your class file, you may have a method to do the trick. The object that will be copied is the input parameter. The object that receives the data would be the implicit parameter. It takes more code, but this will make an actual copy of an object. Now we will address another issue. What happened to static? If you recall, all or most of our methods to this point in the programs we've used thus far have included the keyword static. In our class files, it's been missing. It has to do with how state and behavior are created and what the selector is called. Each object is built with its own set of instance variables and its own copy of all of the methods. That is because none of them have been declared static. So when would a variable or method be declared static? Let me build an example for you. Suppose we want to build account numbers by using the year, account holder's name and a sequential number, something like this. This may lead us to define the account number as a string which might be more practical than making it an integer. Thanks to abstraction, a change like this won't be a problem. Client programs use class methods to get and set the number so the data type of this field doesn't really matter to those clients. Changing it should not have an effect on the client programs if they were written in accordance with good object-oriented principles. To build account numbers, we might write a method in our class like this one. This method would be private because it would only be used by the objects in the class, not the clients. Note we've changed the type of the account number to a string. You can imagine we have other private methods to create the year portion of the account number and hash the account holder's name. This would then be concatenated with a unique sequence number that was incremented each time a new account was created. Let's look at the constructor class. We no longer want to allow the client that is invoking the constructor to supply the account number. We will create that ourselves. And we don't want a default constructor anymore, one that simply doesn't fill in any of the fields. This would enable clients to create empty or dummy accounts and that would not be useful. Our improved constructors rely on the method to build a proper account number. We would also need to delete the set number method because we don't want client programs changing account numbers. How can we keep track of this sequential number? We need this to generate sequence numbers for the accounts. We could create it in the client programs, but it describes the state of the class and should therefore be included in the class. Every object needs to access an increment the same tally. This should be done each time an account object is created. Naturally, this count should be private. Only objects will need to access it directly. To solve the problem of a shared variable, we use a static field. It is declared in the class file just like the instance variables, but using the keyword static, we prevent an instance from being copied into each object upon creation. The method that use this field will still be found in each object, however. An object of the class can reference this private static field directly, but they will be referencing the same field that all the other objects of the class are using. Each object accesses and updates the same count. We want to create a constant or final field that is associated with the class. We would use public static final in that case. It could be accessed by clients because it is public. It is static so there will only be one copy for the class and the keyword final as before makes this a constant. It is accessed by the client using the class name since it is not associated with any particular instance of the class. Objects of the class can access the constant directly. Finally, we might find it optimal to create static methods in our class. These method definitions would reside in the class, not copied to each object. We might create a static method if the method could possibly be called even if no objects had been created by client programs yet. Perhaps we want to see the current interest rate for all accounts. Calling the method requires that we use the class name. Another reason for creating a static method might be to reflect that a particular method, the part of the behavior of the class uses more than one object. It may make sense to call it this way, again using the class name. This lesson has itself been an excellent example of the value of abstraction and its many layers. We've learned just enough implementation details about objects to help us understand, not just memorize, how to use them with these familiar constructs. But we haven't bothered to go any deeper into notions of memory management, storage and so on. As you continue to study, you may find it necessary to go further into some of these areas. What you will find will not be conflicting, but will further illuminate what you've learned so far. In the meantime, we've got a little more to go in our lessons on classes. To gain more practice with the concepts covered in this lecture, make some changes to your client file. Create arrays of account objects and call some methods. Create methods that take account objects as input parameters. Change the constructors and test them by creating objects back in the client file. The more you practice and use these ideas, the more comfortable you will be with them. Now that you've completed this lesson, you should understand why objects act the way they do, when they are used in an array, made equal to one another or passed as parameters. You should also understand how to apply the static keyword to create variables and methods that are part of the class definition, but not stored in any single object. By knowing how to use objects in all of these situations, you can build more powerful code that is both correct and optimized for reuse. Welcome to the next lesson in the module on classes in Java, which explains how classes and methods can be generalized so that they can be reused with generic parameters of different types. After completing this lesson, you'll understand how Java generics enable the passing of types as parameters to the definition of classes and methods. You'll also recognize the benefits that generics offer to Java programmers, including stronger type checking at compile time and greater code reuse. Finally, you'll know some of the restrictions associated with using Java generics effectively in practice. We use the account class covered in a previous lesson as a running example to demonstrate the application of Java generics. Since Java generics are a bit trickier to use than conventional Java classes, we provide many URLs at the bottom of the slides that will give you further insight into Java generics properly. Recall our earlier discussion about the number field in the account class we were building in the previous lesson. We initially defined this field as an int data type. After we worked with the class for a while, we made the design decision to change the number field from an int to a string type to accommodate the way we were generating account ID numbers. One issue that arises when we change is how it affects reuse. In particular, one of the many aims of a class is to reuse it in many different scenarios. Suppose the string account number was suitable for some uses, whereas the int account number was better for others. Should we create two different classes, one of each implementation of the number field? This approach isn't scalable since multiple versions of the same class are harder to maintain and evolve over time. Moreover, the rest of the account class works just fine for both types of projects. What about including two fields in the class, int num and string num, and only use the one needed for any particular implementation? That approach is also a bad idea and will lead to errors and confusion later down the road. Additionally, we can find a good solution in Java generics which is a variant of the generic programming paradigm that allows algorithms and data structures to be written in terms of a placeholder type. These placeholders are later filled in when concrete types are provided as parameters when an object of the generic class is instantiated. A Java class can be parameterized via the Java generics feature which enables the passing of abstract data types or ADTs as type parameters to the definition of a class and its methods. As a result, the class's methods can be written once yet are able to operate on objects of the generic class instantiated with various ADTs all while providing compile time type safety. For example, we can apply Java generics to define the account number type as a generic type parameter to the account class discussed at the beginning of this lesson rather than hard coding the number field in the account class as either a string or an end or writing multiple versions of account. Objects of the generic account class can be instantiated by passing the desired numbered type such as string or integer as a type parameter to account. Note that in Java 7 and beyond the compiler can deduce the type arguments to the new operator so it doesn't need to be provided explicitly. A generic class in Java is defined using the syntax shown on this slide. The type parameter section is enclosed by angle brackets which follow the name of the class. This section specifies the type parameters such as T1, T2 up to and including Tn. For example it's easy to update the account class to use generics. You simply create a generic type declaration by changing the code public class account to public class account number which introduces the type parameter number that can be used anywhere inside the account class such as the type of the number field as a parameter passed to methods and as a return type of methods. Generics offer several benefits to Java programmers. First they eliminate the duplication of code adhering to the don't repeat yourself principle which states that every piece of knowledge must have a single unambiguous authoritative representation within a system. For example rather than having to maintain multiple implementations of account class with different representations of the account number field we could instead have a single generic account class that's parameterized by the type of account number such as string or integer. Another benefit of Java generics is that they ensure compile type safety when operating on different types of ADTs. For example an account object parameterized with the string ADT will not accept a value of type integer. Likewise an account object parameterized with integer ADT would not accept a value of type string. There are some restrictions on using Java generics that you'll need to know to use them effectively in practice. In particular it's not possible to instantiate generic types of primitive types. For example the generic account class cannot be instantiated with the primitive type int but instead must use the non-primitive integer type. Likewise it's not possible to create a new instance of a type parameter. For example a default number cannot be created though Java reflection can be used to accomplish this sort of initialize for general type parameters whose constructors require no arguments. In addition it's not possible to declare static fields whose types are type parameters since static fields are shared by all non-static objects in a class. For example we can't define a static default account number field in the account class. These and other restrictions of Java generics are largely due to its type erasure semantics where the Java compiler avoids creating new classes for parameterized types to ensure generics incur no runtime overhead in the Java virtual machine. Whenever there are multiple ways to represent key properties of a class it's worth considering whether these variations can be handled via Java generics. Now that you've completed this lesson you should understand how Java generics enable the passing of types as parameters to the definition of classes and methods. You should also recognize the benefits that generics offers to Java programmers. Finally you should know some restrictions associated with using generics effectively in practice. When generics are used properly within the constraints of Java's runtime environment they provide powerful capabilities such as stronger type checking at compile time and systematic reuse via generic programming. Generics are used heavily throughout Java's class libraries, especially the Java collections framework which defines generic classes to implement common type safe reusable abstract data type collections such as ArrayList Vector and HashMap which in turn can be parameterized by other types such as an ArrayList of integers, a vector of doubles or a HashMap of employees. For more coverage and examples of Java generics especially its advanced features such as wild cards used to represent unknown types please see the tutorials listed on this slide. Welcome to the next module in our MOOC on Java for Android. With a firm understanding of Java classes under our belt we are ready to explore its support for inheritance and polymorphism as well as its support for interfaces which are similar to classes. This module includes several lessons so we'll first give you a brief roadmap of where we are headed before getting started with the rest of the lessons. When you begin lesson 2 you will learn about inheritance in Java and how inheritance can help us to write code that is easily reused and refactored. In lesson 3 we will see an inheritance at work learning how to build constructors and other methods taking full advantage of the class from which an object was derived. In lesson 4 we will learn about polymorphism and how this principle of object oriented programming affects method calls. In lesson 5 we will see interfaces, a feature of Java that gives us more flexibility when designing classes. And finally in lessons 6 and 7 we will see several advanced features of classes in Java. So let's continue to build on the foundation of all the work you've done so far. Let's get started with this first full lesson on class hierarchy and interfaces in Java. We will begin by learning to recognize the need for subclasses and inheritance hierarchies in Java programs using an example to help motivate key design choices. After completing this lesson you will know how to use the proper syntax for extending existing superclasses to build an inheritance hierarchy. You will also recognize what polymorphism is and be able to write methods that override the methods inherited from a superclass. Finally you will understand how to apply the keyword super to situations where you need to access methods from a superclass. As you've no doubt noticed there is some new terminology to learn as well. So let's get going. To motivate our discussion of objects in classes consider the design of a game where we have several different types of characters. Or even more accurate you may have been asked to design the classes for the characters and another group or groups will design the gameplay. At first look these characters are very different with different rules of how they move, capture and are captured. But upon closer inspection each of our classes may indeed have a few things in common. For example each object will occupy a current position on the game board. They can be assigned to a team color. They may or may not be captured. And each object will have a certain number of lives. We could consider this the state of a character. These characters also share a common behavior to move. We can take advantage of Java's capability to implement subclasses, superclasses and inheritance to create a hierarchy like this one. The superclass angry blue spike will define all of the state and behavior objects have in common. State and behavior unique to an object will be defined in its own class. We can picture it this way. All of the other characters in our game descend from the angry blue spike class. This will be the simplest character in our game. After defining a superclass we can begin defining subclasses. For example, class Kobe is a subclass of the A B spike class. Class wingback is also a subclass of the A B spike class. Consider what we will include in the superclass A B spike. We may include fields such as color, captured, life, and position. Since position will be defined by both an X and Y coordinate, we will define this field as a two element integer array. Here is what the code of our superclass A B spike would look like. There is nothing new here. It looks just like the class files that we have learned to create in our previous modules. We might also include a constructor in this class. The constructor would set all the field variables. Here is what that code might look like. Simple mutator methods or set methods may include public methods, set, color, and capture, as well as private methods like set position and set life. The private designator is needed for set position and set life because these will be helper methods for a more complex mutator method that will actually move a character as we'll see later. Here is the code of these mutator methods. Notice the use of the keyword this in the set color method. Accessor methods might be included like those pictured here. To access the position of the character we have created two methods getX and getY. This is done to make interaction with a character easier for the user. It is simply a design decision that you may or may not employ yourself. Finally, we include a move method to move a character on the board. It uses the private methods set life and set position if it has been determined that a move is possible. You can also see that we return a Boolean value to the calling program indicating whether or not the move was made. What the calling program does with that information is up to that designer. Don't forget to override the toString method and create a suitable string to display selected fields. Here is an overview of the a, b, spiked class to summarize. The class has four fields that we have labeled as private. There is a constructor for the class and here are two of the public methods. Continuing with the class we have the two private set methods and then the rest of the public methods. Now let's consider how we can leverage the work we have done in the a, b, spiked class when creating the ghoul class. Recall that the ghoul class is descended from the a, b, spiked class. This is a child or subclass. The syntax for a subclass is shown here. We use the keyword extends followed by the name of the superclass. In the body of the subclass we only need to declare any additional fields or define any additional or overridden methods. The subclass will inherit much of its state and behavior from its superclass. Every ghoul object is also an angry blue spike object and therefore has color, captured status, life and a position. All the public methods of the angry blue spike class can be called by a ghoul object as well. What does it mean when we say that all of these state and behaviors are inherited by the ghoul class? We will see in a moment that we don't need to write much code to create a ghoul class. For example, we will only write a constructor and override the move method. But let's take a look at all of this in a little more detail. Here is a code we might see in a client program. A ghoul object gem is created and then gem can invoke the method capture or the method move. Recall however that not every character moves like the angry blue spike does. We need to override the method implementation that ghoul would inherit from the super class ab spike is not how a ghoul will move. We override this method in the ghoul class by writing an alternative implementation to be used by ghoul objects. The ghoul can move diagonally one space in any direction. Here is a slick way you can check that by comparing a ghoul's current position to the proposed new position. We also have to make sure the life level is greater than zero as well. But this is true for all characters in the game. Let's compare these conditions with what we have in the current ab spike method. Notice that once we determine that a proposed move is legal, the act of moving is the same for both the super class and the sub class. And if there is not sufficient life left in the character the result is also the same. I've rearranged the conditions needed in the ghoul class. Now we can see that the entire ab spike move method is actually a part of the proposed ghoul version of the move method. We can capitalize on this to minimize the amount of code we need to write. Why do we keep trying to avoid writing code? There are several good reasons actually. For example, if you and your team spend a fair amount of time writing and testing a method or code segment in the super class, why redevelop or even rewrite it? Just call the already tested code. Avoiding the rewrite of code also means we won't introduce errors when trying to recreate it. Finding errors when there is only one place where each function is performed makes the problem easier to find. We don't have to keep track of where all the copies of that code appear in this program. If we want to change or update code in any way, there is also only one place we would need to go to do that. And finally, it makes our code more easily readable and traceable. But back to our move method in the subclass ghoul. We can replace some of our code with a call to the move method that has already been written in the super class ab spike. Here is the code we would need in the ghoul class to override the move method in the super class ab spike. Notice this method must have the same name, parameter list, and return type in order to override the original method. In this implementation we will need to call the method defined in ab spike. To do this we use the keyword super. If the proposed move is a legal one then we make a call to the move method in the super class. Recall, there the life level will be checked and if that allows a move, the move will be accomplished and the value true returned. Otherwise a value of false is returned. If the move is not legal then there is no need to call the super class method and continue checking life level. We simply return false. Writing this method in the ghoul class will override the original version written in the angry blue spike super class. The example we just looked at writing the move method for the ghoul class is also an introduction to the idea of polymorphism. In a very general sense, polymorphism is the idea that one object can take many forms or stand in for another type of object. Let's see how this is done in our example. To get the big picture, we need to take note of two things. First, the ghoul class was derived from the A B spike class and a ghoul object inherits all of the state and behavior of the A B spike. We even said that the ghoul was also an A B spike. This is commonly referred to as the is a relationship. A ghoul is a A B spike. Secondly, note that when we wrote the move method for the ghoul class we called the move method from the A B spike class using the keyword super. But how could we do this? Isn't the A B spike move method written for A B spike objects? It is, but because a ghoul is an A B spike it can also call that method. Polymorphism allows the ghoul to stand in as an A B spike. In this case, while calling and executing the move method defined in the A B spike class. In fact, as we will see in upcoming lessons in this module, a ghoul object can stand in for an A B spike object anywhere an A B spike object is expected. Why does this work? If you think about it, any method that references an A B spike object will only rely on the state and behavior included in an A B spike object. And all of that was inherited by the ghoul objects. Keep this concept in mind as you move on. We will introduce and highlight more examples to illustrate this key principle. This lesson motivated the need for subclasses and inheritance hierarchies in the design of Java programs. Now that you've completed this lesson, you should know the proper syntax for extending subclasses from existing superclasses to build an inheritance hierarchy. You should also recognize what polymorphism is and be able to write methods that override methods inherited from a superclass. Moreover, you should be able to apply your new understanding of super to situations where you need to access methods from superclasses. There's a self-assessment quiz that accompanies this lesson. I recommend investing some time to work through that quiz before moving on to the next lesson. Welcome to the next lesson on inheritance and polymorphism, where you'll learn more about the benefits of creating an inheritance hierarchy in Java. After completing this lesson, you'll understand what it means to inherit a method. You'll also learn how to build constructors in a subclass that extends a superclass. In addition, you'll recognize the impact of declaring a field or method as protected. Finally, you will be able to classify methods as inherited, overridden, or overloaded. Let's start on this material. You may recall from our previous lesson that we were working on developing the classes for characters in a game and building a hierarchy between the superclass A B Spike and the subclass Ghoul. Methods that are not overridden in a subclass like Ghoul and are public in a superclass like A B Spike, GetLife and IsCaptured, for example, can be called by Ghoul objects even though their definition was never written in the Ghoul file. Methods like these are inherited from the superclass. Let's look at how constructors can be inherited. The constructor we wrote in the A B Spike class performs these actions. In the Ghoul subclass, we'd like most of the same actions, but the life should be set to a default value of 15. We can do this by calling the SetLife method that is written in the A B Spike class method. That method adds the input parameter to the field, which in our case would be positive 5. Here is the code we would need to include in the subclass constructor. But SetLife is a private method and therefore is not visible to the subclass and can't be called by a Ghoul. We should change the keyword to protect it. This will allow subclasses to call the method, but still won't allow client classes residing in a different package to attempt to change the life level directly. This design decision makes sense for what we are trying to accomplish. Here is the complete code for the Ghoul class. Because of inheritance, it's really small. Let's take a closer look at the constructor we have just designed for the subclass. Let's rely on our understanding of how objects are instantiated. When a Ghoul is created, the compiler will first call a constructor of the superclass, in this case, a b spike. Once that work is done, the constructor of the subclass finishes up any code that was written for the constructor. The subclass author can either decide to make an explicit call to some constructor in the superclass using the keyword super, or a call to the default constructor in the superclass will happen automatically. This call to the super constructor needs to be written. But you can see that because the subclass is counting on the inheritance of some fields and or behaviors, the superclass must be called in some way. Let's review private methods and fields before we move on. Private fields and methods are not accessible from outside the class in which they are defined. This means that private fields that are inherited from the superclass may not be directly accessed by the subclass that inherited them unless they use public or protected mutator and accessor methods. Let's try a visual example of the relationship between a superclass and its subclass. Here we have base1 as the superclass and sub2 as the subclass. Code in the class file sub2 can directly access its own private fields and methods. Sub2 can also access protected methods from the superclass base1. And of course, code written anywhere can access public methods from both classes. Sub2 code cannot access private fields directly nor call private methods found in base1. From a client file the rules are pretty straightforward. Public fields and methods can be called by any appropriate object in a client file. A protected field or method can be accessed by any other class file that is in the same package, whether it is a file that defines some new object or is acting as a client file. Private fields or methods cannot be accessed by another class under any circumstances. See here that the method UpdateX is defined in both the superclass and the subclass. This indicates that the method has been overridden in the subclass. If an object of the base1 class calls UpdateX, the version in that class is executed. If an object of the sub2 class calls UpdateX the version in the subclass will be called. The method is overridden. In the case of the method MutateX, we see that the parameter lists are different. An object of the sub2 class can call either of these methods because the version in the superclass was inherited by the subclass. The first call would match the version in the superclass. The second call would match the parameter list and version in the subclass. This is an example of a method that has been overloaded. This lesson focused on increasing your confidence in designing a class hierarchy for different scenarios. Taking advantage of inheritance and polymorphism whenever it helped to increase the reuse and customization of existing classes. Now that you've completed this lesson you should understand what it means to inherit a method. You should also have learned how to build constructors in a subclass that call superclass constructors explicitly and explain what happens when no superclass constructor is called by the designer of a subclass. Moreover you should recognize when to declare state and behaviors as private, protected or public. Finally, by reading well written code, you should be able to classify methods as inherited overridden or overloaded. You should take some time to review this lesson and to make sure that you understand the relationships between these files so far. In particular the self-assessment quiz included with this lesson has an accompanying PDF file that contains some Java code with line numbers. Refer to this file as you attempt the quiz since it will challenge you and solidify your learning thus far. Welcome to the next lesson in the module on inheritance and polymorphism in Java where we'll work on the now familiar equals method and explore the concept of polymorphism in more depth. After completing this lesson you'll be able to implement an equals method in a subclass relying on methods defined by the superclass to simplify your work. Polymorphism as a key object-oriented programming concept and apply this concept to transparently customize methods defined by subclasses in an inheritance hierarchy. Finally, you'll understand how polymorphism can be implemented by the Java compiler and Java virtual machine to dynamically dispatch methods associated with the subclass of the object used to invoke the methods. So let's get started with this material. Let's now consider the equals method and how we can take advantage of inheritance to write it. Here is a good way to write the equals method in a subclass taking full advantage of inheritance. Suppose the superclass has the equals method defined in this way. If we are comparing an object of the superclass cast it as a superclass object and then check for further equality. Then we can check the field X. If it is not an object of the superclass, simply return false. Now we come to writing the equals method for the sub2 class which is a subclass of the base1 class. First, we would like to discover if the object that was passed as a parameter is also an object of the subclass. If it is, then we need to make the appropriate comparisons between the two objects. In most cases that will mean comparing everything between the two objects that was inherited from the superclass and then making the remaining comparisons of the fields that are found in the subclass. Here is the code to accomplish that. We set a local Boolean variable to false. If it turns out that the past object is not of the same class the result will remain false and will be returned. If it is a sub2 object we cast it and then call the equals method of the superclass in this case base1 to make the comparisons and return a Boolean value of the results. We end this method with the results of the comparisons made with any subclass fields and a final result is determined. This result is then returned from the equals method. There was a lot of information on that slide. Let's unpack it a bit by looking at the how why and why it works. The how is the code that we just saw. Use the keyword super to call the equals method of the superclass. The why brings us another term for your object oriented vocabulary. We rely on the code written for the superclass because it makes things like refactoring reusing and debugging easier. Refactoring means that we can change implementation details of our code without changing how other users of our class interact with our code. In our previous example suppose we want to declare two super objects equal if field variable X is greater than or equal to the field of the object being compared. This would affect all of the subclasses and the superclass as well. Usually a subclass object would be compared to other subclass objects using the same test. Change it once in the superclass and no subclass user needs to make any changes at all. This is an example of refactoring. And finally, why does this work? You may not have picked up on it but we used a sub to object as the parameter for the equals method of the superclass. Certainly it will make the call because all objects will qualify as type objects. But is it an instance of a base one object? It is. Because of polymorphism. Polymorphism another term commonly used in object oriented programming allows a subclass to take on the identity of any of its ancestor classes. In our previous example where we were designing characters an atomic ghoul is a ghoul. This means that an atomic ghoul can be used as a parameter where a ghoul object is expected. This works because an atomic ghoul has inherited all of the fields and behaviors of a ghoul object. Any method that was expecting a ghoul can still execute if it receives an atomic ghoul object instead. In the same way an atomic ghoul is an ab spike. This was the superclass from which the ghoul class was derived. Because ghouls inherited all the fields and behaviors of an ab spike object, those same fields and behaviors are passed down to the atomic ghoul class. And finally a ghoul is an ab spike. Let's review objects and method calls before leaving this lesson. First let's see where these calls may take place. A subclass can call any public or protected method that is in its superclass because they are all inherited. For example, code like this may be found in a class file where the method setTotal is protected in the superclass from which the class is derived. An object can invoke any public method from its superclass. Yes, that is similar to the first rule but here I am referring to a call found in a client file. My object is an object instantiated from the subclass and the method getTotal is a public method inherited from its superclass. It must be public as opposed to private or protected because this call is being made from outside the class file. Here are more rules about method calls. In all cases these rules apply to both calls made in a class file as well as calls made on objects instantiated in client files. When an object invokes a method that is inherited from the superclass the compiler will look for the definition of that method in its own class file. If there is no definition there this means that the object is referring to an inherited method so the compiler will then reference the superclass of the object. If nothing is found there then it must be a method that is a superclass first inherited from its superclass and so on. Suppose the method called is overloaded meaning that the name of the method is defined more than once but the parameter list differ. The first priority is to find a method definition with matching return type and parameter list. Once again the compiler would look for the definition in the first class file of the object. Then in the parent class and in the parent of the parent class and so on until a suitable definition is found. Because of polymorphism and inheritance this object can use any of the public methods found in its ancestor classes and the subclass file can also use the protected methods. What if a method is overridden? Recall overridden refers to the notion that there are several methods with the same name, return type and parameter list found in different subclass files and superclass files. It enables clients to write code that is very readable, like this while invoking two different methods definitions. Once again the compiler looks in the subclass that made the call first then the superclass and so on. If the object actually wants to invoke an overridden method in the parent class file that must be set up in the subclass. You might see this in something like the to string method. The subclass will most likely override this method. But what if we wanted to make both versions of the to string method available to the subclass? In the subclass file we would define the overridden method to string along with other methods that might call the parent class version the key word super and the subclass's own version or just call the parent class version by itself. In the client file the calls would look like this. Notice the first call to print object x is an implicit call of to string. The other two calls must be made explicitly to methods written in that subclass. A client file cannot use the key word super to try to make the subclass method. That reference must be made in the class file itself as a design decision made by the author of the class. And this is in keeping with our ideas about abstraction. Users of a class should not know what methods are native and what methods are inherited. They should just be able to interact with the object in useful ways. You don't need to know how polymorphism is implemented easily, such as to create subclasses that override the equals and to string methods defined in superclasses as discussed above. However, understanding how polymorphism works will increase your qualifications as a coveted full stack developer since you'll be more familiar with other layers in the Android stack and development tool chain. It will also help you to design object-oriented programs that strike the appropriate balance between flexibility and efficiency. Polymorphism in Java is implemented via the Java compiler and the Java virtual machine or JVM, which contains a bytecode instruction that calls the appropriate method for an object at runtime which is a process commonly known as dynamic dispatch. The specific method that's dynamically dispatched corresponds to the method associated with the subclass of the object used to invoke the method. This subclass method can override and customize the method inherited from the object superclass. Dynamic dispatch is also known as virtual method invocation, which is the default dispatching mechanism for methods in Java. Therefore, a subclass can override any method defined in a superclass, unless that method is declared as private, final, or static. Although the Java virtual machine specification does not mandate a particular internal structure for objects, a Java compiler typically generates a virtual table or vtable for each Java class. This vtable contains the addresses of the dynamically dispatched virtual methods in the classes API. Likewise, the Java compiler generates a pointer to the vtable of the class associated with each Java object. This so-called vptr, vpointer, is used internally by the JVM to locate the appropriate method in the vtable and dispatch it whenever a virtual method is called by an app. Java's dynamic dispatching mechanism is also commonly referred to as late binding, since virtual method calls are not bound until the time of invocation. In addition to supporting polymorphism via dynamic method dispatching, Java also supports static method dispatching where the implementation of a method is selected at compile time rather than at run time. JVM uses this technique to dispatch Java's private, final and static methods. For example, the static eq method in abstract map is statically dispatched to compare whether two objects are equal. Although statically dispatched methods cannot be overridden by subclasses, the underlying JVM can implement and optimize them more efficiently and dynamically dispatched methods since fewer instructions are typically required to invoke a statically dispatched method. These types of methods therefore play an important role in certain types of Java apps that value performance more than extensibility, such as time critical apps where the right answer delivered too late becomes the wrong answer. Now that you've completed this lesson you should be able to implement an equals method in a subclass relying on methods defined by the superclass to simplify your work. You should also be able to recognize polymorphism as a key object-oriented programming concept and be able to apply that concept to transparently customize methods defined by subclasses in an inheritance hierarchy. In addition, you should now understand how polymorphism can be implemented by the Java compiler and Java virtual machine to dynamically dispatch methods associated with the subclass of the object used to invoke the methods. This lesson underscores how concepts you learned in previous lessons continue to resurface as they apply to new scenarios. To refine your understanding therefore, you should continually apply these concepts by coding your own examples trying out your own ideas about classes and objects and in particular, try coding some of the examples contained in recent lessons if you haven't already. Make changes and then see if you can explain the results that you've seen. Trial, error and success can be powerful learning tools. We know our MOOC students lead very busy lives so please don't code and drive. Welcome to another lesson on class hierarchy and interfaces in Java. Now that we have a good foundation in classes and inheritance hierarchies we'll discuss interfaces which is yet another feature of Java. After completing this lesson you'll understand the similarities and differences between Java's class and interface features so you can evaluate programming problems and apply the best solutions. You will also be able to provide examples that contrast between these two features. Finally, you'll also know the proper syntax needed to implement the interface features presented in this lesson. So let's get started. Once again, it's much easier to discuss the ideas of object oriented programming in Java if we have an example in front of us. Consider these four objects you might find in a to-do list app that helps to schedule items an errand, a bill, a workout and a social engagement. Each has a very different way to define the state of the object and so each has different fields. We can't even say that their behavior is necessarily the same but the way in which clients would interact with these objects is the same. Each of these objects can be scheduled on a particular date and each can be marked as completed. They may also have other unique behaviors but we want to focus on what they have in common. Clearly these items cannot be arranged into a hierarchy. Superclasses and subclasses won't work here but we should be able to take some advantage of their similar behaviors. For example, to schedule an errand we would consider the deadline, the time it will take to complete and then try to find a time slot that works. To schedule an engagement we might check the requested date and then generate some sort of RSVP. In both cases we'd like to keep the call to the schedule event similar and simple. This keeps code readable and easy to write. Although a hierarchy is out of the question we can still take advantage of some of the benefits of code reuse by designing an interface. A JALA interface includes public method headings that's name, return type and parameter list but it doesn't include any body, no implementation. Like this method header for the method completed. This is all that we would see in the interface. Interface name should be capitalized. The file name and the interface name must match just like a class file and the file you write will end in .java, again just like a class file. But there should be no constructors no instance variables nor any bodies of any of the public methods written. Interfaces will never be instantiated. They do not contain the necessary information to create an object. They act as a form for methods that implement that interface to follow when it comes to defining methods. You can see what I mean in the next slide. Here is an interface called item that includes two public method headers schedule and complete. These are two behaviors that will be common to all the classes that implement this interface. But the implementation details of how each class accomplishes the method will be quite different. The class errand implements the interface item. Arend can have instance variables constructors, accessors and mutators necessary to model the class but it must also implement all of the methods listed in the interface. In this case, we have two schedule and complete. Another class engagement also implements the interface item. Its instance variables and methods can be completely different from those found in Arend. But it must also implement the two methods provided by the interface. There is no inheritance at work here, like we saw between superclasses and subclasses. We have two classes, Arend and engagement, that both invoke the same method schedule but with two very different implementations. Finally, an interface can be used as a parameter type. Polymorphism makes this possible because every class that implements the item interface is an item, it can be passed as an item to a method. Here is an example of a method to schedule any unfinished items for tomorrow and mark them as complete on today's list to close out the day. Because each of these items can implement both schedule and completed, we could pass an engagement, an Arend, or any other object that implements the item interface. You have now added knowledge of interfaces to your growing knowledge of Java object-oriented programming features. Now that you've completed this lesson, you should understand the similarities and differences between Java classes and interfaces. You should also be able to provide examples that contrast these two features. Finally, you should know the proper syntax needed to implement the interface features presented in this lesson. As we wrap up this lesson, try coming up with a couple of scenarios where a Java interface would be appropriate. For example, developing classes of shipping containers like flats and boxes could be facilitated with a shipping container interface that included methods for capacity and dimension. Try designing a few interfaces yourself. Be sure you aren't simply designing a class hierarchy and burdening it by forcing an interface where one is not needed. Welcome to the next lesson in this module, where we'll dive deeper into some advanced topics related to classes, interfaces, inheritance, and polymorphism in Java. After completing this lesson, you should understand what abstract classes and methods are and how they differ from concrete classes and methods. You'll also recognize how abstract classes compare and contrast with Java interfaces. In addition, you'll learn how Java supports various types of nested classes that are defined within the scope of an enclosing class. Not every Java program uses these advanced Java features. But once you are familiar with them, you'll be able to read and write more powerful apps in Android. Up to this point, we've been focusing our discussion on concrete classes, which are classes that implement all of their defined methods so that they can be instantiated directly to create and manipulate objects. The ghoul class is a good example of this. It's also possible and often quite useful in Java to define so-called abstract classes and or methods. These classes and methods create what we refer to as abstract types that provide an incomplete implementation or no implementation at all and can be used to define and enforce a protocol, a protocol that must be supported by subclasses. For example, the class abstract map is an abstract superclass that defines certain methods that must be implemented by all map implementations such as hash map and tree map. An abstract method is a method that's declared without any implementation. In other words, the method signature is followed by a semicolon rather than an opening and closing brace containing the method definition. An abstract class is a class that is declared with the keyword abstract before the keyword class. An abstract class may or may not include abstract methods. For example, the abstract map abstract superclass defines the abstract entry set method. An abstract class can't be instantiated directly, but it can be extended by a subclass. If that subclass provides implementation of its abstract methods, then instances of the subclass can be created. For example, it's not possible to create an instance of abstract map since its entry set method is defined as abstract. However, it is possible to create an instance of hash map which extends abstract map and provides an implementation of entry set. Abstract classes and abstract methods are used in many Java and Android class libraries to create inheritance hierarchies whose methods must be overridden by subclasses to transparently customize their behavior. Now that we've covered both Java interfaces and abstract classes in earlier discussions, we can compare and contrast them. Abstract classes are similar to interfaces in many respects. For example, neither can be instantiated directly, but instead must be customized either by subclassing in the case of an abstract class or implementing in the case of an interface. They both can contain methods declared without any implementation. However, abstract classes have additional capabilities that go beyond what's available in Java interfaces. For example, abstract classes can define fields that are not static nor final. Likewise, abstract classes can define public, protected, and private concrete methods. In contrast, interfaces can only define public, static, and final fields, and all methods must be public. Moreover, in releases of Java prior to version 8, methods in an interface cannot be implemented. Another difference between a class and an interface is that a class can only extend one class whether or not it is abstract. Conversely, a class can implement any number of interfaces. In addition to allowing developers to create top-level classes within a package, Java also enables one or more classes to be defined within an enclosing class. Classes organized in this manner are called nested classes. For example, Java Vector is a top-level class that defines several nested classes to handle its various iterator mechanisms used to access each element in a vector without exposing details of the vector's internal implementation. Nested classes provide several benefits, including grouping together classes that are only used in one place to avoid creating additional files. For example, nesting the iter and vector splitterer classes within the vector class enables all these classes to reside within the vector.java file. Nested classes also increase encapsulation by hiding implementation classes that needn't be visible to other top-level classes. For example, the nested iter class is defined as private, so it can't be accessed by clients that use vector. Finally, nested classes enhance accountability by placing nested classes within top-level classes, so the nested classes are defined close by to where they are used by programmers. For example, the iter nested class is used by the iterator factory method defined directly above it, and the vector splitterer class is used by the splitterer factory defined directly above it. There are two types of nested classes. An inner class is a nested class that can reference non-static methods and fields in the enclosing class. For example, iter is an inner class that can access the mCount field defined by the vector top-level class. Likewise, next method in iter can invoke the element data method defined by vector. A static class is a nested class that can't reference non-static methods and fields defined in the enclosing top-level class. For example, vector splitterer is a static nested class that doesn't access any fields or methods defined in vector, but instead uses fields it defined privately to maintain its own state. This lesson focused on several advanced Java features that once mastered will greatly enhance your ability to read and write powerful apps in Android. Now that you've completed this lesson, you should understand what abstract classes and methods are and how they differ from concrete classes and methods. You should also recognize how abstract classes compare and contrast with Java interfaces. In addition, we've also learned how Java supports various types of nested classes that are defined within the scope of an enclosing class. Java is a large and ever-evolving development and runtime platform. Be prepared to continue expanding your knowledge of its features, both in the context of Android and beyond. In the meantime, don't let the contents of this lesson rattle you. Begin working on the programming assignment for this module if you haven't already. Review the material, apply what you have learned, and reinforce your understanding by building, breaking, fixing, and rebuilding these programs. Welcome to the next lesson in this module, which focuses on Java support for exception handling, which involves both an extensible hierarchy of classes and a set of virtual machine mechanisms that separate the control flow paths of normal app execution from the control flow paths of anomalous app execution. After completing this lesson, you'll know why exceptions are needed to make Java apps more robust and easier to understand and evolve. You'll also understand how exceptions are reported and handled in Java apps. Finally, you'll recognize the two main types of exceptions that are supported via Java's hierarchy of exception subclasses. Despite our best efforts, apps will occasionally encounter problems that just can't be ignored. Echoing the classic Murphy's Law, anything that can go wrong will go wrong. For example, problems can arise when an app attempts to open a file that is not available on the device, or tries to call a method or access a field via a null reference, or indexes into an array before or after the valid range of the array. To provide a nicely structured way of dealing with these types of problems, Java provides an exception handling mechanism that enables the logic of an app to differ in a structured way, so the control flow paths of normal app execution is clearly and cleanly separated from the control flow paths of anomalous app execution. Exceptions in Java are supported by both an extensible hierarchy of classes and a set of mechanisms provided by the underlying virtual machine that systematically handle problems arising during the execution of an app. If an error condition occurs in a block of Java code in an app, that block can throw an exception to notify another part of the app that a problem has occurred. This notification allows the part of the app that catches the exception to take the appropriate action in response, which may include interacting with the user to fix the problem, logging the problem, or exiting the app altogether. Any code can report the occurrence of an error condition by calling throw with the appropriate instance of an exception class. For example, if the initial capacity passed to the vector constructor is less than 0, a new illegal argument exception object can be thrown to the portion of code that tried to create a vector erroneously. Likewise, if the index value passed to vectors last index of method is beyond the bounds of the vector, then a new index out of bounds exception object is thrown. When an exception is thrown, the virtual machine performs a number of steps. For example, consider an app with a group of methods that are called in a particular order, where method 1 calls method 2, which performs some computations, and then calls method 3, which in turn performs other computations, and ultimately calls method 4. Let's assume that method 4 throws an IO exception, which can occur under various circumstances, such as trying to write a downloaded image to a file when there's no space available on the storage device. When method 4 throws the IO exception, normal program execution stops. Control then transfers to the appropriate exception handler, which may involve the virtual machine searching up the runtime call stack to find an appropriate handler for the IO exception. For the sake of discussion, we'll have method 1 catch the IO exception and perform the appropriate action, such as informing the user that the storage device is full. The Java language provides some syntax for handling exceptions. A try block contains a sequence of one or more statements that encloses a region of code that may throw exceptions. For example, this try block encloses a statement that defines a vector of strings. This vector is passed a negative number as its initial capacity, which of course is an error. One or more catch blocks can be associated with a try block. A catch block defines an exception handler that handles the type of exception indicated by its argument. For example, this catch block handles the illegal argument exception thrown by the vector constructor when it is passed an initial capacity less than 0. Another syntactic element associated with Java exceptions is the finally block which always runs no matter how the try block is exited. For example, this finally block is always run to unlock the lock regardless of whether the statements within the try block throw an exception or if the try block returns from the method. Yet another syntactic element associated with Java exceptions is the try with resources block which was introduced in Java 7. This variant of a try lock declares one or more resources that will be closed automatically after the app's flow of control exits the block. For example, this try with resources block defines a variable called buff reader which is used within the block to read a new line. The close method of the buff reader variable is automatically closed when the try with resources block exits thereby ensuring that any resources it allocates are released. Java exceptions are organized into a class hierarchy all of which inherit from the exception superclass. Handlers can be specified for different subclasses of exception. For example, a try block could be followed by two catch blocks one for the index out of bounds exception and another for the illegal argument exception both of which are descendants of the exception superclass. If a method doesn't specify a handler for an exception that's thrown the next matching handler up the runtime stack gets called. For example, method one handles method two within a try block. Method two then calls method three without using a try block. So it has no way to handle any exceptions method three may throw. Therefore, if method three throws some exception it won't be handled in method two but instead will be handled back in method one's catch block which handles some exception. To handle every possible type exception in a method simply define a catch block that handles exception which as a superclass forms the base of the Java exception inheritance hierarchy. Moreover, to handle every possible type of error define a catch block that handles throwable which is the superclass of all recoverable runtime errors and exceptions in the Java language. A useful method defined by throwable and thus available to all exception subclasses is print stack trace which prints a back trace of all methods on the runtime stack leading up to the location where the exception occurred. This back trace can be extremely helpful when locating bugs in your apps. There are two general types of exceptions supported by Java. One type is called checked exceptions. Methods declaring checked exceptions require their callers to provide an exception handler or else the compiler will flag the calling code as an error. For example, the right object method in the vector class explicitly declares that it may throw the IO exception. Therefore, if method one calls the right object method on a vector object it must contain a catch block that catches the IO exception. The second general type of exception supported by Java is called an unchecked exception which can be thrown by a method without it having explicitly declared the exception in its signature. For example, method A can throw an unchecked exception such as the index out of bounds exception. Method B can call method A without having to define a catch block for the index out of bounds exception. Moreover, it could define a catch block for a more general exception such as the exception superclass. In fact, method B could catch the index out of bounds exception as an exception and then re-throw it as a new runtime exception. Although we've covered quite a bit of material in this lesson there's still more to learn about Java exceptions. So we recommend you read more about these topics in various online Java resources. This lesson focus on exception handling in Java which involves both an extensible hierarchy of classes and a set of virtual machine mechanisms that separate the control flow paths of normal app execution from the control flow paths of anomalous app execution. Now that you've completed this lesson you should know why exceptions are needed to make Java apps more robust and easier to understand and evolve. You should also now understand how exceptions are reported and handled in Java apps. Finally, you should recognize the two main types of exceptions that are supported via Java's hierarchy of exception subclasses. Even well-written apps occasionally encounter problems that just can't be ignored. So Java's exception handling mechanism provides a nicely structured way of dealing with these problems. Welcome to the last module in this MOOC. This module guides you through the final programming assignment which is a so-called mini project designed to give you more freedom designing and implementing a creative solution that applies all the object-oriented Java programming language features we've covered in this MOOC. In this mini project you'll develop a simple calculator app which provides the means to add, subtract, multiply, and divide numbers input by a various Android user interface components. After completing the lesson in this module you'll understand the requirements of the calculator app, know how to download the Android Studio project and associated files that provide the skeleton of the app, be familiar with guidelines for structuring your Java solution to receive full credit and submit your solution and assess solutions submitted by other learners in this MOOC. If you've successfully completed the programming assignments in the previous modules you should be well prepared to develop a creative and functioning implementation of the calculator app. So let's get started. In this mini project assignment you'll write the program logic needed to complete a simple calculator app in Java. This app will perform integer arithmetic on values entered via components using Android's user interface, or UI. We'll supply you with skeleton code that implements the calculator's UI and Android. The app you implement should meet the following requirements. The UI we provide allows the user to enter two integer values and select one of four operations addition, subtraction, multiplication, or division. After supplying the two integer values and pressing the calculate button on the UI three entities will be provided to the Java code you write. The two integer values entered by the user and the operation they selected to perform on these values. Your code must then perform the necessary computation and print a strain that contains the final answer in the expected form. The final results printed for integer addition, subtraction, and multiplication are what you'd expect them to be as shown in these screenshots. The first screenshot shows performing addition, the second shows performing subtraction, and the third shows performing multiplication. However, the final result printed for integer division must include both the quotient and the remainder, even if the remainder is zero, as shown in these screenshots. This screenshot shows performing division with a zero remainder, and this screenshot shows performing division with a non-zero remainder. Please start this assignment by downloading the supplied zip file corresponding to this mini project. Extract the contents of the zip file onto your computer. The contents extracted from this zip file contain an Android Studio project. Next, launch Android Studio and load the project. In addition to the UI-related classes, which you can ignore for the time being, you'll see this project supplies you with five skeleton files containing the following Java classes. The logic.java file contains the process method, which receives the three entities passed from the UI. The two integers upon which to perform the computation, and an integer value indicating the operation to perform, with a value one equals addition, two equals subtraction, three equals multiplication, and four equals division. Naturally, we recommend using symbolic constants for these values rather than magic numbers. There are four other files. The add.java file contains an empty class named add. The subtract.java file contains an empty class named subtract, the multiply.java file contains an empty class named multiply, and the divide.java file contains an empty class named divide. Your work should start by modifying the logic.java skeleton file. Open this file on the Android Studio integrated development environment and look for the comment to do, start your code here. You can then add your implementation at this location as you see fit. Likewise, open the other four java skeleton files and follow similar steps until you've completed your implementation. For a more detailed analysis of the skeleton files and other parts of the UI code, please watch the lesson entitled mini project assignment walkthrough. We'll now discuss the guidelines for structuring your solution, which are divided into two parts. The first part are guidelines for source code design. Given the intentionally limited capabilities of the calculator app, one solution might involve performing all the work in the process method via a multi-branch if else statement. However, this design would be unmanageable if we later wanted to extend our calculator to support additional operations and or add additional data types. We therefore encourage you to create an object-oriented solution that will provide better abstraction to simplify extensibility and refactoring the future. In particular, to receive full credit for this assignment, you must apply java language features we taught in recent modules of the MOOC and use the four empty java classes we provided by adding methods and or instance variables to them. We also recommend you consider defining a java interface that these four empty classes implement. The second set of guidelines involves source code aesthetics, such as commenting, indentation, spacing and identifier names. They're required to properly indent your code and will lose points if you make significant indentation mistakes or inconsistencies. None of your lines of code should be longer than 80 characters. Please also use a programming style that's easy to read and maintain by doing things like creating additional helper methods as needed, using meaningful variable and method names, making the code more readable by using white space and blank lines appropriately and explaining tricky pieces of code with useful comments. For this assignment, you'll need to submit a zip file containing all the java files and android studio project files needed to compile and run your calculator app. To build this zip file open the gradle window in android studio which is located along the far right edge of the screen all the way up. Then go to the M8 assignment calculator tasks other menu item and double click on project zip to generate the zip file of your project in the project root directory zip folder. After you locate the zip file on your drive you can upload it to the Coursera platform. Unlike previous assignments in this MOOC that were auto graded this mini project will be purely peer assessed which involves giving and receiving feedback from other learners in the MOOC. There are two steps involved in peer assessing programming assignments. First, you'll submit your assignment by following the steps we just discussed at which point you'll be granted access to a video that walks through our solution so you can see how we implemented the calculator app. Second, you'll then review five submissions made by your peers. Using a grading rubric we supply you with to guide your peer assessments. Your final grade on this mini project will be calculated using the median scores you receive from your peers on each assignment component. There's a 20% penalty for not evaluating your peers so please make sure to follow these instructions so that everyone benefits from helpful feedback. As you do your evaluation please keep an open mind and focus on the positive. Our goal is not to find every way to deduct points over small deviations from the requirements or for legitimate differences in implementation styles. Therefore, look for ways to give points when it's clear the submitter has given a good faith effort to do the project and when it's likely they've succeeded. Finally, remember that almost everyone is working hard and putting in serious effort so if you've got doubts please err on the side of giving too many points rather than giving too few. Congratulations! You've now finished all the contents of this MOOC. The final mini project in this module gives you experience developing a simple calculator app in Java that provides the means to add, subtract, multiply and divide numbers input by the Android user interface components. Now that you've completed the material in this module you should understand the requirements of the calculator app. Know how to download the Android Studio project and associated files containing the app's skeleton. Be familiar with guidelines for structuring your Java solution to receive full credit and recognize how to submit your solution and assess solutions submitted by other learners in this MOOC. On behalf of my co-instructors Mike, Jerry and Julie we hope you've enjoyed learning how to program Java for Android. We also look forward to working with you in subsequent MOOCs in our specialization on Android app development. This video performs a code walkthrough of the skeleton files you can find for the mini project assignment in Module 8. We'll start by opening up the project clicking on the particular files and choosing that in Android Studio that we'll go ahead and open up the project then go take a look at the project click down to find the files that you're down here and we'll start by taking a look at the skeletons that you have to fill in to perform your work. We'll start first by looking at the logic interface. The logic interface is a Java interface that defines the API for processing user calculations. As you can see here it has one method called process that takes the first argument and the second argument passed in from the user interface which we'll examine later as well as the operation that's been selected by the user and it goes ahead and performs the operation on those particular arguments. Let's go take a look at the logic file you can see the logic class implements the logic interface which means you have to come along and implement this process method that's where your code will go. You can also see that we keep a reference to the activity output here which is used to interact with the activity from within this code and then we also have constructor that takes the activity output reference and stores it in this field that's part of the logic class. As usual we do this in order to be able to decouple the Java portion of the code from the Android portion so you can focus your solution purely on the Java portion. Let's now go ahead and take a look at the various files as we mentioned in the earlier video these are all empty files you can see add which is a class divide which is a class multiply which is a class and subtract which is a class and your job as part of this assignment is to figure out how to implement each of these different classes and then connect them together with the logic class so when process is called back you'll go ahead and do the appropriate computations in order to perform the operation to add, divide, multiply, or subtract that's basically what you have to do so your job is to figure out the appropriate design, figure out the appropriate implementation using the various Java features that we've been talking about throughout this MOOC things like interfaces and classes and inheritance and polymorphism and so on in order to be able to implement this calculator logic for completeness we'll also walk you through the user interface, keep in mind this is not what you actually have to do you don't have to write this code, we provided it to you but it might be fun to see how it works we'll go over here and take a look at the main activity as you can see here this activity provides the user interface that prompts the user for two integer values as well as for the operation to perform on these values main activity extends activity and implements activity interface we'll come and take a look at activity interface in just a second let's go ahead and take a look at some of the fields that are provided in the main activity class we have something called a spinner which is a drop-down selector that you can use to choose which operation to use there's also a button that you can press when you want to perform the computation after you've entered the values you can enter value one and value two and that means you can add things to them and then there's going to be a result that's also stored in an edit text that stores the results of the computation that's where the output is actually stored we also have a reference to the logic object that of course is what you'll be implementing over here with the logic class that we looked at before that you have to go ahead and fill in there's also something that's called an array adapter and this is used to adapt an array of character array of characters or character sequence care sequence to make it usable by the math spinner and this we'll see later on when the program actually runs now let's get into a little bit of Android callback methods these are called lifecycle hook methods we'll be discussing a lot more about these in the second MOOC in the specialization where we talk about activities in more detail one of the things that the Android environment does for you the Android platform does for you is it has certain hook methods that are called back automatically by the Android platform by the framework portion of the Android platform in order to initialize your activity objects activities are the ways that you interact with the user they provide user facing operations in this case it's the GUI that's used by the calculator to get the input and the operation and then present the output what we do here is we do a call up to the super class just kind of always done in Android code we'll talk about that more in the next MOOC you don't have to worry about that here we call a method to initialize the various views and other fields that are part of the activity and then the final thing we do is we go ahead and we create a new logic object passing in this activity and this is actually this which is the object that implements the activity and that is actually going to be used to give the activity interface to the logic object that we defined over here so if you look over here you can see we're passing in something called activity interface and we'll come back and talk about what that means in a second this is going to get stored in a field called mLogic so that's now available to interact with the code that you write here's the initialize UI method this again is a lot of detail that we'll talk about more in the next MOOC so don't worry about understanding it I'm just going through it now for completeness we set the layout the user will see the user interface with the calculate button and the two edit text fields to get the input and the edit text field to present the output down here we then go ahead and get a bunch of references to the various view objects these are things that are part of the user interface widgets or the user interface interactors components the button, the edit text fields the thing called the math spinner which allows you to be able to select the result and the result object then we go ahead and create an adapter which is going to be used to allow us to visualize the spinner and the last thing we do is we go ahead and we add we make the default selection for the math spinner to be add so if you don't do anything to the contrary you'll end up adding the two inputs that are given by the user naturally if you want to change that you can go ahead and click on the spinner and it'll select the other operations to perform when a user actually presses a button that goes ahead and is automatically dispatched by the android framework to the button pressed method right here and that will go ahead and get the operation number we'll take a look at how that works in a second once we've got the operation number we get the first value and the second value that's specified by the user and the user interface and here is then the hook that connects with the code that you write we end up calling the process callback method or hook method on the logic reference with arg1, arg2 and the operation and that vectors you over here where this code is going to be run, the code that you write there if you go down a little bit and take a look at some of these helper methods you see get value 1 and get value 2 essentially take the string that was given through the user input and converts that into an integer for value 1 and for value 2 those are returned as ints and then down here we also have a way of being able to select the appropriate choice from the math spinner to get the appropriate operation as an operation number so I think add is 1, subtract is 2 multiply is 3 divide is 4 and so on and so forth here then is the way in which we print the result to the user output this is something of course that you'll end up needing to call from within your logic process method when you're all done you'll go ahead and call back and you'll print the result which just goes ahead and sets the text for the result to be the text string, the string that's passed in here so that's basically how the activity works let's now go take a quick look at the activity interface if you take a look up here you'll see that the main activity implements activity interface here's activity interface as you can see the activity interface simply provides some ways of getting at various values that the user provided in this particular case the only one that really matters is the print method we provide the other ones here just if necessary but they're actually passed in as you can see as the value of argument one argument two an operation so that's actually not strictly necessary here we only really need to provide the print method and we use this activity interface in order to be able to have a very loose coupling between the activity the math activity that we define here which is all android code and then the code that's over here in the so called logic folder and this is the code that by and large is just plain old java code and so you don't have to really know much if anything about android in order to be able to carry out this computation whereas that allows us to be able to write the android activity over here we're doing that in this course for a couple reasons the main reason is so we don't have to teach you everything you need to know about android at this point and then later when we get to the next course we'll teach you more about how these things work and we're also doing this because it makes it easier to mock up various test applications to test the logic here without having to drag in all the android operations and the android platform and the android framework and that of course was used earlier in order to make it easier to write unit tests we could use with our auto graders here's a bit more this again is stuff we'll cover in the next class these are some of the resources that are provided as part of the android studio environment to dictate the way in which information is laid out on the screen here's activity underscore main XML if you go over here to main activity you can see that there's a reference to activity main here we do the set content view call that basically says that this will be the main activity for or rather the main layout for this activity so if we go take a look at this it's going to be a xml file and there we go it's showing you what the view looks like so you can see we have value one value two you've got spinner here which gives you the different items you have the calculate button and then you've got the output edit text for the result so those are some of the things that you get here here's what this actually looks like in the xml format and I'm not going to go through this in gory detail right now this is something that we'll cover again in the next MOOC but basically what you can see here is we indicate that this particular text view is going to give you a prompt to edit to enter the value one text and then we're going to have the input for this that's the edit text and it's given a name and we're going to use those names in the main program take a look over here you see we go look those things up by their name come down here we see another prompt which is going to be for edit the value of two edit text we have a calculate button and you can see that this particular xml descriptor says when somebody clicks on this button call back to the button pressed method and if you take a look over here here is button pressed it's right there there's the button press method so what this is doing is it's basically connecting this resource file is connecting the button that's clicked on the user interface with this method that's defined in the android activity and we'll talk again later about other ways of doing that that's just one way of doing it the next MOOC we'll cover that in more detail here's how we define the spinner and here's how we define the results that will be printed out so again you don't have to know about all of this stuff in order to do the assignment I'm just walking it you through it because it's kind of fun to get a preview of what's going to come along later in the course but the main thing to remember for right now is that you need to start focusing on the logic file and filling out how you do the process method and then implementing the ad divide multiply and subtract files and we intentionally made this assignment quite open-ended to give you maximal ability to be creative and that's why we're going to be doing this using peer evaluation as opposed to auto grading because people will do things in different ways and we didn't want to be restricted in the way in which we evaluated it we want to let you guys be as creative as you'd like so that's the walkthrough of the skeletons hope that that is helpful to you and of course as always please feel free to contact us on the discussion forums if you have any questions whatsoever