Skip to content Skip to navigation

OpenStax-CNX

You are here: Home » Content » Ap0140: Self-assessment, Type conversion, casting, common exceptions, public class files, javadoc comments and directives, and null references

Navigation

Recently Viewed

This feature requires Javascript to be enabled.
 

Ap0140: Self-assessment, Type conversion, casting, common exceptions, public class files, javadoc comments and directives, and null references

Module by: R.G. (Dick) Baldwin. E-mail the author

Summary: Part of a self-assessment test designed to help you determine how much you know about type conversion, casting, common exceptions, public class files, javadoc comments and directives, and null references in Java.

Preface

This module is part of a self-assessment test designed to help you determine how much you know about object-oriented programming using Java.

The test consists of a series of questions with answers and explanations of the answers.

The questions and the answers are connected by hyperlinks to make it easy for you to navigate from the question to the answer and back.

I recommend that you open another copy of this document in a separate browser window and use the links to under Listings to easily find and view the listings while you are reading about them.

Questions

Question 1 .

What output is produced by the program shown in Listing 1 ?

  • A. Compiler Error
  • B. Runtime Error
  • C. OK OK
  • D. OK
  • E. None of the above.

Listing 1: Listing 1: Listing for Question 1.

public class Ap151{
  public static void main(
                        String args[]){
        new Worker().doIt();
  }//end main()
}//end class Ap151

class Worker{
  void doIt(){
    Object refA = new MyClassA();
    Object refB = 
              (Object)(new MyClassB());
    System.out.print(refA);
    System.out.print(refB);
    System.out.println("");
  }//end doIt()
}// end class Worker

class MyClassA{
  public String toString(){
    return "OK ";
  }//end test()
}//end class MyClassA

class MyClassB{
  public String toString(){
    return "OK ";
  }//end test()
}//end class MyClassB

Answer and Explanation

Question 2

What output is produced by the program shown in Listing 2 ?

  • A. Compiler Error
  • B. Runtime Error
  • C. OK OK
  • D. OK
  • E. None of the above.

Listing 2: Listing 2: Listing for Question 2.

public class Ap152{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap152

class Worker{
  void doIt(){
    Object ref1 = new MyClassA();
    Object ref2 = new MyClassB();
    System.out.print(ref1);
    
    MyClassB ref3 = (MyClassB)ref1;
    System.out.print(ref3);
    System.out.println("");
  }//end doIt()
}// end class Worker

class MyClassA{
  public String toString(){
    return "OK ";
  }//end test()
}//end class MyClassA

class MyClassB{
  public String toString(){
    return "OK ";
  }//end test()
}//end class MyClassB

Answer and Explanation

Question 3

What output is produced by the program shown in Listing 3 ?

  • A. Compiler Error
  • B. Runtime Error
  • C. OK
  • D. None of the above.

Listing 3: Listing 3: Listing for Question 3.

import java.util.Random;
import java.util.Date;

public class Ap153{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap153

class Worker{
  void doIt(){
    Random ref = new Random(
                 new Date().getTime());
    if(ref.nextBoolean()){
      throw new IllegalStateException();
    }else{
      System.out.println("OK");
    }//end else
  }//end doIt()
}// end class Worker

Answer and Explanation

Question 4

What output is produced by the program shown in Listing 4 ?

  • A. Compiler Error
  • B. Runtime Error
  • C. 5 10 15
  • D. None of the above.

Listing 4: Listing 4: Listing for Question 4.

import java.util.NoSuchElementException;
public class Ap154{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap154

class Worker{
  void doIt(){
    MyContainer ref = 
                     new MyContainer();
    ref.put(0,5);
    ref.put(1,10);
    ref.put(2,15);
    
    System.out.print(ref.get(0)+" ");
    System.out.print(ref.get(1)+" ");
    System.out.print(ref.get(2)+" ");
    System.out.print(ref.get(3)+" ");  

  }//end doIt()
}// end class Worker

class MyContainer{
  private int[] array = new int[3];
  
  public void put(int idx, int data){
    if(idx > (array.length-1)){
      throw new 
              NoSuchElementException();
    }else{
      array[idx] = data;
    }//end else
  }//end put()
    
  public int get(int idx){
    if(idx > (array.length-1)){
      throw new 
              NoSuchElementException();
    }else{
      return array[idx];
    }//end else
  }//end put()
    
}//end class MyContainer

Answer and Explanation

Question 5

The source code in Listing 5 is contained in a single file named Ap155.java

What output is produced by the program?

  • A. Compiler Error
  • B. Runtime Error
  • C. OK
  • D. None of the above.

Listing 5: Listing 5: Listing for Question 5.

public class Ap155{
  public static void main(
                        String args[]){
    new Ap155a().doIt();
  }//end main()
}//end class Ap155

public class Ap155a{
  void doIt(){
    System.out.println("OK");
  }//end doIt()
}// end class Ap155a

Answer and Explanation

Question 6

A Java application consists of the two source files shown in Listing 6 and Listing 7 having names of AP156.java and AP156a.java

What output is produced by this program?

  • A. Compiler Error
  • B. Runtime Error
  • C. OK
  • D. None of the above.

Listing 6: Listing 6: Listing for Question 6.

public class Ap156{
  public static void main(
                        String args[]){
    new Ap156a().doIt();
  }//end main()
}//end class Ap156

Listing 7: Listing 7: Listing for Question 6.

public class Ap156a{
  void doIt(){
    System.out.println("OK");
  }//end doIt()
}// end class Ap156a

Answer and Explanation

Question 7

Explain the purpose of the terms @param and @return in Listing 8 . Also explain any of the other terms that make sense to you.

Listing 8: Listing 8: Listing for Question 7.

public class Ap157{
    
/**
* Returns the character at the 
* specified index. An index ranges from
* <code>0</code> to 
* <code>length() - 1</code>.
*
* @param  index  index of desired 
* character.
* @return  the desired character.
*/
  public char charAt(int index) {
    //Note, this method is not intended
    // to be operational.  Rather, it
    // ...
    return 'a';//return dummy char
  }//end charAt method
}//end class

Answer and Explanation

Question 8

What output is produced by the program shown in Listing 9 ?

  • A. Compiler Error
  • B. Runtime Error
  • C. Tom
  • D. None of the above.

Listing 9: Listing 9: Listing for Question 8.

public class Ap158{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap158

class Worker{
  void doIt(){
    char[] ref;
    System.out.print(ref);
    System.out.print(" ");
    ref[0] = 'T';
    ref[1] = 'o';
    ref[2] = 'm';
    System.out.println(ref);
  }//end doIt()
}// end class Worker

Answer and Explanation

Question 9

What output is produced by the program shown in Listing 10 ?

  • A. Compiler Error
  • B. Runtime Error
  • C. Tom
  • D. None of the above.

Listing 10: Listing 10: Listing for Question 9.

public class Ap159{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap159

class Worker{
  void doIt(){
    char[] ref = null;
    System.out.print(ref);
    System.out.print(" ");
    ref[0] = 'T';
    ref[1] = 'o';
    ref[2] = 'm';
    System.out.println(ref);
  }//end doIt()
}// end class Worker

Answer and Explanation

Question 10

What output is produced by the program shown in Listing 11 ?

  • A. Compiler Error
  • B. Runtime Error
  • C. Joe Tom
  • D. None of the above.

Listing 11: Listing 11: Listing for Question 10.

public class Ap160{
  public static void main(
                        String args[]){
        new Worker().doIt();
  }//end main()
}//end class Ap160

class Worker{
  void doIt(){
    char[] ref = {'J','o','e'};
    System.out.print(ref);
    System.out.print(" ");
    ref[0] = 'T';
    ref[1] = 'o';
    ref[2] = 'm';
    System.out.println(ref); 
  }//end doIt()
}// end class Worker

Answer and Explanation

Listings

I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the listings while you are reading about them.

Miscellaneous

This section contains a variety of miscellaneous information.

Note:

Housekeeping material
  • Module name: Ap0140: Self-assessment, Type conversion, casting, common exceptions, public class files, javadoc comments and directives, and null references
  • File: Ap0140.htm
  • Originally published: 2004
  • Published at cnx.org: 12/18/12
  • Revised: 11/17/13

Note:

Disclaimers:

Financial : Although the Connexions site makes it possible for you to download a PDF file for this module at no charge, and also makes it possible for you to purchase a pre-printed version of the PDF file, you should be aware that some of the HTML elements in this module may not translate well into PDF.

I also want you to know that, I receive no financial compensation from the Connexions website even if you purchase the PDF version of the module.

In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle books, and placed them for sale on Amazon.com showing me as the author. I neither receive compensation for those sales nor do I know who does receive compensation. If you purchase such a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it was made and published without my prior knowledge.

Affiliation : I am a professor of Computer Information Technology at Austin Community College in Austin, TX.

Answers

Answer 10

C. Joe Tom

Explanation 10

This is an upgrade to the program from Question 9 .

Success at last

The code in the following fragment resolves the compilation problem from Question 8 and the runtime problem from Question 9 .

Note:
  void doIt(){
    char[] ref = {'J','o','e'};
    System.out.print(ref);
    System.out.print(" ");
    ref[0] = 'T';
    ref[1] = 'o';
    ref[2] = 'm';
    System.out.println(ref); 
  }//end doIt()

Simply initializing the local reference variable named ref satisfies the compiler, making it possible to compile the program.

Initializing the local reference variable named ref with a reference to a valid array object eliminates the NullPointerException that was experienced in Question 9 .

Printing the contents of the array object

The print statement passes the reference variable to the print method. The print method finds that the reference variable refers to a valid object (instead of containing null as was the case in Question 9 ) and behaves accordingly.

The print statement causes the initialized contents of the array object to be displayed. Then those contents are replaced with a new set of characters. The println statement causes the new characters to be displayed.

Back to Question 10

Answer 9

B. Runtime Error

Explanation 9

Purposely initializing a local variable

This is an update to the program from Question 8 . The code in the following fragment solves the compilation problem identified in Question 8 .

Note:
  void doIt(){
    char[] ref = null;

In particular, initializing the value of the reference variable named ref satisfies the compiler and makes it possible to compile the program.

A NullPointerException

However, there is still a problem, and that problem causes a runtime error.

The following statement attempts to use the reference variable named ref to print something on the screen. This results, among other things, in an attempt to call the toString method on the reference. However, the reference doesn't refer to an object. Rather, it contains the value null .

Note:
    System.out.print(ref);

The result is a runtime error with the following infamous NullPointerException message appearing on the screen:

Note:
java.lang.NullPointerException
 at java.io.Writer.write(Writer.java:107)
 at java.io.PrintStream.write(PrintStream.java:245)
 at java.io.PrintStream.print(PrintStream.java:396)
 at Worker.doIt(Ap159.java:22)
 at Ap159.main(Ap159.java:15)

Back to Question 9

Answer 8

A. Compiler Error

Explanation 8

Garbage in, garbage out

Earlier programming languages, notably C and C++ allowed you to inadvertently write programs that process the garbage left in memory by previous programs running there. This happens when the C or C++ programmer fails to properly initialize variables, allowing them to contain left-over garbage from memory.

Member variables are automatically initialized to default values

That is not possible in Java. All member variables in a Java object are automatically initialized to a default value if you don't write the code to initialize them to some other value.

Local variables are not automatically initialized

Local variables are not automatically initialized. However, your program will not compile if you write code that attempts to fetch and use a value in a local variable that hasn't been initialized or had a value assigned to it.

Print an uninitialized local variable

The statement in the following code fragment attempts to fetch and print a value using the uninitialized local variable named ref .

Note:
  void doIt(){
    char[] ref;
    System.out.print(ref);

As a result, the program refuses to compile, displaying the following error message under JDK 1.3.

Note:
Ap158.java:23: variable ref might not have been initialized
    System.out.print(ref);

Back to Question 8

Answer 7

See explanation below.

Explanation 7

The javadoc.exe program

When you download the JDK from Oracle, you receive a program named javadoc.exe in addition to several other programs.

The purpose of the javadoc program is to help you document the Java programs that you write. You create the documentation by running the javadoc program and specifying your source file or files as a command-line parameter. For example, you can generate documentation for this program by entering the following at the command line.

Note:
javadoc Ap157.java

Produces HTML files as output

This will produce a large number of related HTML files containing documentation for the class named Ap157 . The primary HTML file is named Ap157.html . A file named index.html is also created. This file can be opened in a browser to provide a viewer for all of the information contained in the many related HTML files.

(As a labor saving device, you can also specify a group of input files to the javadoc program, using wildcard characters as appropriate, to cause the program to produce documentation files for each of the input files in a single run.)

Special documentation comments and directives

If you include comments in your source code that begin with

/**

and end with

*/

they will be picked up by the javadoc program and become part of the documentation.

In addition to comments, you can also enter a variety of special directives to the javadoc program as shown in the following program.

Note:
public class Ap157{
    
/**
* Returns the character at the 
* specified index. An index ranges from
* <code>0</code> to 
* <code>length() - 1</code>.
*
* @param  index  index of desired 
* character.
* @return  the desired character.
*/
  public char charAt(int index) {
    //Note, this method is not intended
    // to be operational.  Rather, it
    // is intended solely to illustrate
    // the generation of javadoc
    // documentation for the parameter
    // and the return value.
    return 'a';//return dummy char
  }//end charAt method
}//end class

The @param and @return directives

The @param and @return directives in the source code shown above are used by the javadoc program for documenting information about parameters passed to and information returned from the method named charAt . The method definition follows the special javadoc comment.

Back to Question 7

Answer 6

C. OK

Explanation 6

Public classes in separate files

This program meets the requirement identified in Question 5 . In particular, this program defines two public classes. The source code for each public class is stored in a separate file. Thus, the program compiles and executes successfully, producing the text OK on the screen.

Back to Question 6

Answer 5

A. Compiler Error

Explanation 5

Public classes in separate files

Java requires that the source code for every public class be contained in a separate file. In this case, the source code for two public classes was contained in a single file. The following compiler error was produced by JDK 1.3:

Note:
Ap155.java:18: class Ap155a is public, should be declared in a file 
named Ap155a.java
public class Ap155a{

Back to Question 5

Answer 4

This program produces both of the following:

  • C. 5 10 15
  • B. Runtime Error

Explanation 4

The NoSuchElementException

This program defines, creates, and uses a very simple container object for the purpose of illustrating the NoSuchElementException .

The code in the following fragment shows the beginning of a class named MyContainer from which the container object is instantiated.

Note:
class MyContainer{
  private int[] array = new int[3];
  
  public void put(int idx, int data){
    if(idx > (array.length-1)){
      throw new 
              NoSuchElementException();
    }else{
      array[idx] = data;
    }//end else
  }//end put()

A wrapper for an array object

This class is essentially a wrapper for a simple array object of type int . An object of the class provides a method named put , which can be used to store an int value into the array. The put method receives two parameters. The first parameter specifies the index of the element where the value of the second parameter is to be stored.

Throw NoSuchElementException on index out of bounds

The put method tests to confirm that the specified index is within the positive bounds of the array. If not, it uses the throw keyword to throw an exception of the type NoSuchElementException . Otherwise, it stores the incoming data value in the specified index position in the array.

(Note that a negative index will cause an ArrayIndexOutOfBoundsException instead of a NoSuchElementException to be thrown.)

The get method

An object of the MyContainer class also provides a get method that can be used to retrieve the value stored in a specified index.

Note:
  public int get(int idx){
    if(idx > (array.length-1)){
      throw new 
              NoSuchElementException();
    }else{
      return array[idx];
    }//end else
  }//end put()

The get method also tests to confirm that the specified index is within the positive bounds of the array. If not, it throws an exception of the type NoSuchElementException . Otherwise, it returns the value stored in the specified index of the array.

(As noted earlier, a negative index will cause an ArrayIndexOutOfBoundsException instead of a NoSuchElementException to be thrown.)

The NoSuchElementException

Thus, this container class illustrates the general intended purpose of the NoSuchElementException .

Instantiate and populate a container

The remainder of the program simply exercises the container. The code in the following fragment instantiates a new container, and uses the put method to populate each of its three available elements with the values 5, 10, and 15.

Note:
  void doIt(){
    MyContainer ref = 
                     new MyContainer();
    ref.put(0,5);
    ref.put(1,10);
    ref.put(2,15);

Get and display the data in the container

Then the code in the next fragment uses the get method to get and display the values in each of the three elements, causing the following text to appear on the screen:

5 10 15

Note:
    System.out.print(ref.get(0)+" ");
    System.out.print(ref.get(1)+" ");
    System.out.print(ref.get(2)+" ");

One step too far

Finally, the code in the next fragment goes one step too far and attempts to get a value from index 3, which is outside the bounds of the container.

Note:
    System.out.print(ref.get(3)+" ");

This causes the get method of the container object to throw a NoSuchElementException . The program was not designed to handle this exception, so this causes the program to abort with the following text showing on the screen:

Note:
5 10 15 java.util.NoSuchElementException
 at MyContainer.get(Ap154.java:49)
 at Worker.doIt(Ap154.java:30)
 at Ap154.main(Ap154.java:15)

(Note that the values of 5, 10, and 15 were displayed on the screen before the program aborted and displayed the error message.)

Back to Question 4

Answer 3

This program can produce either of the following depending on the value produced by a random boolean value generator:

  • B. Runtime Error
  • C. OK

Explanation 3

Throwing an exception

This program illustrates the use of the throw keyword to throw an exception.

(Note that the throw keyword is different from the throws keyword.)

Throw an exception if random boolean value is true

A random boolean value is obtained. If the value is true, the program throws an IllegalStateException and aborts with the following message on the screen:

Note:
java.lang.IllegalStateException
 at Worker.doIt(Ap153.java:29)
 at Ap153.main(Ap153.java:20)

If the random boolean value is false, the program runs to completion, displaying the text OK on the screen.

Instantiate a Random object

The following code fragment instantiates a new object of the Random class and stores the object's reference in a reference variable named ref .

Note:
  void doIt(){
    Random ref = new Random(
                 new Date().getTime());

I'm not going to go into a lot of detail about the Random class. Suffice it to say that an object of this class provides methods that will return a pseudo random sequence of values upon successive calls. You might think of this object as a random value generator.

Seeding the random generator

The constructor for the class accepts a long integer as the seed for the sequence.

(Two Random objects instantiated using the same seed will produce the same sequence of values.)

In this case, I obtained the time in milliseconds, relative to January 1, 1970, as a long integer, and provided that value as the seed. Thus, if you run the program two times in succession, with a time delay of at least one millisecond in between, the random sequences will be different.

Get a random boolean value

The code in the next fragment calls the nextBoolean method on the Random object to obtain a random boolean value. (Think of this as tossing a coin with true on one side and false on the other side.)

Note:
    if(ref.nextBoolean()){
      throw new IllegalStateException();

Throw an exception

If the boolean value obtained in the above fragment is true, the code instantiates a new object of the IllegalStateException class , and uses the throw keyword to throw an exception of this type.

Program aborts

The program was not designed to gracefully handle such an exception. Therefore the program aborts, displaying the error message shown earlier.

Don't throw an exception

The code in the next fragment shows that if the boolean value tested above is false, the program will display the text OK and run successfully to completion.

Note:
    }else{
      System.out.println("OK");
    }//end else
  }//end doIt()

You may need to run the program several times to see both possibilities.

Back to Question 3

Answer 2

The answer is both of the following:

  • D. OK
  • B. Runtime Error

Explanation 2

One cast is allowable ...

It is allowable, but not necessary, to cast the type of an object's reference toward the root of the inheritance hierarchy.

It is also allowable to cast the type of an object's reference along the inheritance hierarchy toward the actual class from which the object was instantiated.

Another cast is not allowable ...

However, (excluding interface type casts) , it is not allowable to cast the type of an object's reference in ways that are not related in a subclass-superclass inheritance sense. For example, you cannot cast the type of an object's reference to the type of a sibling of that object.

Two sibling classes

The code in the following fragment defines two simple classes named MyClassA and MyClassB . By default, each of these classes extends the class named Object . Therefore, neither is a superclass of the other. Rather, they are siblings.

Note:
class MyClassA{
  public String toString(){
    return "OK ";
  }//end test()
}//end class MyClassA

class MyClassB{
  public String toString(){
    return "OK ";
  }//end test()
}//end class MyClassB

Instantiate one object from each sibling class

The code in the next fragment instantiates one object from each of the above classes, and stores references to those objects in reference variables of type Object.

Then the code causes the overridden toString method of one of the objects to be called by passing that object's reference to the print method.

Note:
  void doIt(){
    Object ref1 = new MyClassA();
    Object ref2 = new MyClassB();
    System.out.print(ref1);

The code in the above fragment causes the text OK to appear on the screen.

Try to cast to a sibling class type

At this point, the reference variable named ref1 holds a reference to an object of type MyClassA . The reference is being held as type Object .

The statement in the next fragment attempts to cast that reference to type MyClassB , which is a sibling of the class named MyClassA .

Note:
    MyClassB ref3 = (MyClassB)ref1;

A ClassCastException

The above statement causes a ClassCastException to be thrown, which in turn causes the program to abort. The screen output is shown below:

Note:
OK java.lang.ClassCastException:MyClassA
 at Worker.doIt(Ap152.java:24)
 at Ap152.main(Ap152.java:14)

(Note that the text OK appeared on the screen before the program aborted and displayed diagnostic information on the screen.)

Back to Question 2

Answer 1

C. OK OK

Explanation 1

Type conversion

This program illustrates type conversion up the inheritance hierarchy, both with and without a cast.

Store object's reference as type Object

The following fragment instantiates a new object of the class named MyClassA , and stores that object's reference in a reference variable of type Object . This demonstrates that you can store an object's reference in a reference variable whose type is a superclass of the class from which the object was instantiated, with no cast required.

Note:
class Worker{
  void doIt(){
    Object refA = new MyClassA();

Cast object's reference to type Object

The code in the next fragment instantiates an object of the class named MyClassB , and stores the object's reference in a reference variable of type Object , after first casting the reference to type Object . This, and the previous fragment demonstrate that while it is allowable to cast a reference to the superclass type before storing it in a superclass reference variable, such a cast is not required.

Note:
    Object refB = 
              (Object)(new MyClassB());

Type conversion and assignment compatibility

This is part of a larger overall topic commonly referred to as type conversion. It also touches the fringes of something that is commonly referred to as assignment-compatibility.

Automatic type conversions

Some kinds of type conversions happen automatically. For example, you can assign a value of type byte to a variable of type int and the type conversion will take place automatically.

Cast is required for narrowing conversions

However, if you attempt to assign a value of type int to a variable of type byte , the assignment will not take place automatically. Rather, the compiler requires you to provide a cast to confirm that you accept responsibility for the conversion, which in the case of int to byte could result in the corruption of data.

Automatic conversions up the inheritance hierarchy

When working with objects, type conversion takes place automatically for conversions toward the root of the inheritance hierarchy. Therefore, conversion from any class type to type Object happen automatically. However, conversions in the direction away from the root require a cast.

(Conversion from any class type to any superclass of that class also happens automatically.)

Polymorphic behavior

The code in the next fragment uses polymorphic behavior to display the contents of the two String objects.

Note:
    System.out.print(refA);
    System.out.print(refB);

No cast required

This works without the use of a cast because the print method calls the toString method on any object's reference that it receives as an incoming parameter. The toString method is defined in the Object class, and overridden in the String class. Polymorphic behavior dictates that in such a situation, the version of the method belonging to the object will be called regardless of the type of the reference variable holding the reference to the object.

When would a cast be required?

Had the program attempted to call a method on the reference that is not defined in the Object , class, it would have been necessary to cast the reference down the inheritance hierarchy in order to successfully call the method.

Back to Question 1

-end-

Content actions

Download module as:

Add module to:

My Favorites (?)

'My Favorites' is a special kind of lens which you can use to bookmark modules and collections. 'My Favorites' can only be seen by you, and collections saved in 'My Favorites' can remember the last module you were on. You need an account to use 'My Favorites'.

| A lens I own (?)

Definition of a lens

Lenses

A lens is a custom view of the content in the repository. You can think of it as a fancy kind of list that will let you see content through the eyes of organizations and people you trust.

What is in a lens?

Lens makers point to materials (modules and collections), creating a guide that includes their own comments and descriptive tags about the content.

Who can create a lens?

Any individual member, a community, or a respected organization.

What are tags? tag icon

Tags are descriptors added by lens makers to help label content, attaching a vocabulary that is meaningful in the context of the lens.

| External bookmarks